设计模式的分类
我们都知道有 23 种设计模式,这 23 种设计模式可分为如下三类:
- 创建型模式(5 种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
- 结构型模式(7 种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式(11 种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式系列文章传送门
什么是观察者模式
观察者模式是一种典型的发布订阅模式,定义了对象间的一种一对多的依赖关系,只要一个对象的状态发生改变,其依赖的所有相关对象都会得到通知并做出想要,是一种行为型模式。
观察者模式的组成
- 抽象被观察者:也叫主题,定义了一个接口,接口中提供了注册观察者、删除观察者、通知观察者方法。
- 具体被观察着:也叫具体主题,实现了抽象被观察者接口,重写了其方法,并维护了一个观察者列表,当被观察者状态发生变化的时候,通知观察者列表中的所有观察者。
- 抽象观察者:也叫订阅者,定义了一个接口,并在接口中定义了一个更新的方法。
- 具体观察着:也叫具体订阅者,实现了抽象观察者接口,并实现具体的更新方法,也就是自己的业务逻辑。
抽象者模式案例演示
我们使用生活中的微信公众号信息推送来演示观察者模式,当我们订阅了某个微信公众号之后,公众号更新了内容的时候会给我们推送消息,这里公众号就是被观察者(主题),用户就是观察者(订阅者)。
Subscriber(抽象观察者)
Subscriber 抽象观察者定义了一个更新的接口,具体代码如下:
public interface Subscriber {
//订阅者更新接口
void update(String message);
}
SubscriberImpl(具体观察者)
SubscriberImpl 具体观察者,实现了抽象观察者的更新接口,具体代码如下:
public class SubscriberImpl implements Subscriber {
public String userName;
public SubscriberImpl(String userName) {
this.userName = userName;
}
@Override
public void update(String message) {
System.out.println(userName + "订阅的公众号更新内容为:" + message);
}
}
OfficialAccount(抽象被观察者)
OfficialAccount 定义了新增、删除、通知观察者(订阅者)的方法,具体代码如下:
public interface OfficialAccount {
//添加订阅者
void addSubscriber(Subscriber subscriber);
//删除订阅者
void deleteSubscriber(Subscriber subscriber);
//通知订阅者
void notifySubscriber(String message);
}
OfficialAccountImpl(具体被观察者)
OfficialAccountImpl 实现了抽象被观察者接口,实现了新增、删除、通知观察者(订阅者)的方法,具体代码如下:
public class OfficialAccountImpl implements OfficialAccount {
//订阅者列表
public List<Subscriber> subscriberList = new ArrayList<>();
@Override
public void addSubscriber(Subscriber subscriber) {
subscriberList.add(subscriber);
}
@Override
public void deleteSubscriber(Subscriber subscriber) {
subscriberList.remove(subscriber);
}
@Override
public void notifySubscriber(String message) {
for (Subscriber subscriber : subscriberList) {
subscriber.update(message);
}
}
}
ObserverClient(客户端代码)
ObserverClient 模拟出发观察者模式,代码如下:
public class ObserverClient {
public static void main(String[] args) {
OfficialAccountImpl officialAccount = new OfficialAccountImpl();
//订阅者
SubscriberImpl subscriberOne = new SubscriberImpl("小明");
SubscriberImpl subscriberTwo = new SubscriberImpl("小美");
//添加订阅者
officialAccount.addSubscriber(subscriberOne);
officialAccount.addSubscriber(subscriberTwo);
//通知订阅者订阅消息
officialAccount.notifySubscriber("早间新闻~朝闻天下");
//移出 订阅者 防止内存泄漏
officialAccount.deleteSubscriber(subscriberOne);
officialAccount.deleteSubscriber(subscriberTwo);
System.out.println("使用完成要及时移出订阅者对象,防止内存泄漏");
//移出完订阅者后 就不会出发消息订阅
officialAccount.notifySubscriber("早间新闻~朝闻天下");
}
执行结果如下:
小明订阅的公众号更新内容为:早间新闻~朝闻天下
小美订阅的公众号更新内容为:早间新闻~朝闻天下
使用完成要及时移出订阅者对象,防止内存泄漏
可以看到我们我们调用通知方法后,订阅者都订阅到了消息,结果符合预期。
特别注意:观察者使用完成后要及时移除掉,防止内存泄漏。
观察者模式的优缺点
优点:
- 松耦合,订阅者和被订阅者之间只知道对方的接口,并不关注具体实现,降低了代码耦合度。
- 代码灵活性良好,可以动态的增加减少观察者(订阅者)。
- 扩展性良好,新增观察者(订阅者)并不需要修改被观察者代码。
缺点:
- 使用观察者模式需要定义被观察者和观察者的类和接口,增加了系统的类。
- 注意内存泄漏问题和循环引用问题。
观察者模式的使用场景
- 当一个对象的状态发生变化的时候,需要通知多个对象时的场景。
- 发布订阅的场景,发布一个主题,需要多个订阅者来订阅。
总结:本篇简单分享了观察者模式的概念和使用,并使用公众号订阅消息的方式来进行了案例演示,希望可以帮助到需要的朋友。
如有不正确的地方欢迎各位指出纠正。