设计模式之美学习-行为型-观察者模式(二十六)

什么是观察者模式

在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知,被依赖对象为被观察者,依赖对象为观察者

在实际开发中有多种叫法::Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener

设计模式其实要干的事情就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦,具体到观察者模式,它是将观察者和被观察者代码解耦。借助设计模式,我们利用更好的代码结构,将一大坨代码拆分成职责更单一的小类,让其满足开闭原则、高内聚松耦合等特性,以此来控制和应对代码的复杂性,提高代码的可扩展性

常见的应用方式

/**
 * 定义观察者接口
 */
public interface Subject {
    //注册观察者
    void registerObserver(Observer observer);
    //删除观察者
    void removeObserver(Observer observer);
    //发起通知
    void notifyObservers(Message message);
}

/**
 * 定义被观察者接口
 */
public interface Observer {
    void update(Message message);
}

public class ConcreteSubject implements Subject {
    //存储被观察者
    private List<Observer> observers = new ArrayList<Observer>();

    //注册
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
   //删除
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
   //发起通知
    @Override
    public void notifyObservers(Message message) {
        //循环调用被观察者通知方法
        for (Observer observer : observers) {
            observer.update(message);
        }
    }

}

//被观察者实现1
public class ConcreteObserverOne implements Observer {
    //接收通知
    @Override
    public void update(Message message) {
        //TODO: 获取消息通知,执行自己的逻辑...
        System.out.println("ConcreteObserverOne is notified.");
    }
}

//被观察者实现
public class ConcreteObserverTwo implements Observer {
    //接收通知
    @Override
    public void update(Message message) {
        //TODO: 获取消息通知,执行自己的逻辑...
        System.out.println("ConcreteObserverTwo is notified.");
    }
}

public class Demo {
    public static void main(String[] args) {
        //创建一个观察者对象
        ConcreteSubject subject = new ConcreteSubject();
        //注册被观察者
        subject.registerObserver(new ConcreteObserverOne());
        subject.registerObserver(new ConcreteObserverTwo());
        //发起通知
        subject.notifyObservers(new Message());
    }
}

注册场景应用

需求

假设我们在开发一个 P2P 投资理财系统,用户注册成功之后,我们会给用户发放投资体验金。代码实现大致是下面这个样子的

原始代码

public class UserController {
    private UserService userService; // 依赖注入
    private PromotionService promotionService; // 依赖注入

    public Long register(String telephone, String password) {
        //省略输入参数的校验代码
        //注册
        long userId = userService.register(telephone, password);
        //发放体验金
        promotionService.issueNewUserExperienceCash(userId);
        return userId;
    }
}

注册里面做了2个事情一个是注册一个是发放体验金违反单一职责原则,如果不大量更改以下代码可以接收.

如果需要大量更改,比如后续注册成功增加发送短信提醒,我们再register方法增加一行发送短信违反了开闭原则,我们可以通过观察者模式来实现

重构后

//被观察者抽象接口
public interface RegObserver {
    void handleRegSuccess(long userId);
}

//发送体验金
public class RegPromotionObserver implements RegObserver {
    private PromotionService promotionService; // 依赖注入

    @Override
    public void handleRegSuccess(long userId) {
        promotionService.issueNewUserExperienceCash(userId);
    }
}

//发送短信
public class RegNotificationObserver implements RegObserver {
    private NotificationService notificationService;

    @Override
    public void handleRegSuccess(long userId) {
        notificationService.sendInboxMessage(userId, "Welcome...");
    }
}

public class UserController {
    private UserService userService; // 依赖注入
    //被观察者
    private List<RegObserver> regObservers = new ArrayList<>();

    // 一次性设置好,之后也不可能动态的修改
    public void setRegObservers(List<RegObserver> observers) {
        regObservers.addAll(observers);
    }

    public Long register(String telephone, String password) {
        //省略输入参数的校验代码
        //省略userService.register()异常的try-catch代码
        long userId = userService.register(telephone, password);
        //注册成功 通知被观察者
        for (RegObserver observer : regObservers) {
            observer.handleRegSuccess(userId);
        }

        return userId;
    }
}

异步非阻塞模式

可以查看Guava EventBus使用

原文地址:https://www.cnblogs.com/LQBlog/p/12671716.html