前面我已经学写了创建型的四种 单例式 工厂式 建造者模式,原型模式这是为了解决对象的创建问题,

结构型为了解决类和对象的组合和组装问题有代理模式,桥接模式,装饰模式,适配器模式,门面模式,组合模式,享元模式

现在学习行为型设计模式,为了解决类和对象支间的交互问题

这是第一个行为型设计模式,我们一共要学习11个,

观察者模式

也被叫做发布订阅模式,其含义为在对象之间定义一个一对多的依赖,当这个对象的状态发生改变的时候,会通知所有依赖的对象,在实际的项目开发中,观察者和被观察者的称呼很灵活,比如Subject-Observer等,不过,不管怎么说,只要场景符合就行

下面给出了一种最简单的实现方式

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);

}

}

}

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) {

//省略输入参数的校验代码

//省略userService.register()异常的try-catch代码

long userId = userService.register(telephone, password);

promotionService.issueNewUserExperienceCash(userId);

return userId;

}

}

这个接口做了两件事,一件是注册,一件是发放体验金

如果为了应对未来的接口需求变化,我们可以改为

观察者模式,在注册成功的时候,其他的系统在用户系统中的注册都会得到提示,从而执行对应的任务

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;

}

}

上面就是在注册成功了,有两个要执行的注册的观察者被触发了,这样的接口逻辑,也符合开闭原则

其实,大部分设计模式所在做的工作,就是在解耦,创建型模式,就是讲创建一个对象和使用对象解耦,结构型,则是将不同功能之间解耦,行为型模式就是讲不同的行为解耦

然后说回观察者模式

小到代码层面的解耦,大到架构层面的系统解耦,都可以应用观察者模式,比如邮件订阅

对于不同的应用场景下,可以有不同的实现方式,有同步阻塞的,异步非阻塞的异步阻塞的

向上面的场景,如果注册接口调用很频繁,那么可以改为异步非阻塞的实现方式,这样当注册函数执行完成了,就可以直接返回了,剩下的订阅者的执行,就是由一个新的异步线程执行了

甚至说,使用内部的EventsBus

刚刚两个场景,不管是异步还是同步,都是进程内实现的,如果需要系统之间来交互,除了使用一般的RPC接口,还可以使用消息队列来实现

从而做到解耦,这样观察者和被观察者绝对解耦,并不会感知彼此

发表评论

邮箱地址不会被公开。 必填项已用*标注