0 设计模式
不了解设计模式的小伙伴可以通过这篇文章了解一下什么是设计模式
https://blog.csdn.net/qq_42874315/article/details/120006447?spm=1001.2014.3001.5502
1 观察者模式
观察者模式的本质就是监听器,当被监听的源对象(被观察者)触发了事件,对应的观察者就会根据事件做出相应的响应。事件处理通常使用观察者+责任链来实现。
在学习观察者模式之前建议先学习责任链模式的思想:https://blog.csdn.net/qq_42874315/article/details/120229565
2 实现思路
- 在被观察者中聚合监听器(链式)和事件
- 被观察者中产生事件,传入到监听器中,监听器去执行
3 需要的类
-
事件接口
-
具体事件
在构造方法中可以进行一些信息的设置,便于后面使用
-
观察者接口
在方法中传入事件
-
观察者
观察到事件后进行的响应操作
-
被观察者
内聚事件对象
定义一个观察者的集合对象(责任链的思想)
定义一个触发方法,这个方法中主要是进行事件的触发,然后通过遍历责任链(同时传入事件)去做出响应
-
测试类
4 具体实现
场景:小孩子随时可能会哭,爸爸、妈妈、Dog三个监听者,去做相应的监听动作
4.1 Event(事件接口)
/**
* 事件抽象类
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:20
*/
public abstract class Event<T> {
abstract T getSource();
}
4.2 WakeUpEvent(事件接口实现类)
/**
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:21
*/
public class WakeUpEvent extends Event<Child> {
long timestamp;
String loc;
Child source;
public WakeUpEvent(long timestamp, String loc, Child source){
this.timestamp = timestamp;
this.loc = loc;
this.source = source;
}
@Override
Child getSource() {
return source;
}
}
4.3 Observer(监听器接口)
/**
* 观察者接口
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:23
*/
public interface Observer {
void actionOnWakeUp(Event event);
}
4.4 监听器接口实现类
4.4.1 Dad
/**
* 观察者
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:24
*/
public class Dad implements Observer{
public void feed(){
System.out.println("dad feed................");
}
@Override
public void actionOnWakeUp(Event event) {
WakeUpEvent wakeUpEvent = (WakeUpEvent) event;
System.out.println("地点:" + wakeUpEvent.loc + ",事件:" + wakeUpEvent.timestamp + ",源对象:" + wakeUpEvent.source);
feed();
}
}
4.4.2 Mum
/**
* 观察者
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:24
*/
public class Mum implements Observer{
public void hug(){
System.out.println("mum hugging......");
}
@Override
public void actionOnWakeUp(Event event) {
WakeUpEvent wakeUpEvent = (WakeUpEvent) event;
System.out.println("地点:" + wakeUpEvent.loc + ",事件:" + wakeUpEvent.timestamp + ",源对象:" + wakeUpEvent.source);
hug();
}
}
4.4.3 Dog
/**
* 观察者
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:24
*/
public class Dog implements Observer{
public void wang(){
System.out.println("dog wangwangwang...");
}
@Override
public void actionOnWakeUp(Event event) {
WakeUpEvent wakeUpEvent = (WakeUpEvent) event;
System.out.println("地点:" + wakeUpEvent.loc + ",事件:" + wakeUpEvent.timestamp + ",源对象:" + wakeUpEvent.source);
wang();
}
}
4.5 Child(被观察者)
/**
* 被观察者
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:22
*/
public class Child {
private String name;
private Event event;
public Child(String name) {
this.name = name;
}
private List<Observer> observers = new ArrayList<>();
{
observers.add(new Dad());
observers.add(new Mum());
observers.add(new Dog());
}
public void wakeUp(){
this.event = new WakeUpEvent(System.currentTimeMillis(),"bed",this);
for (Observer observer : observers) {
observer.actionOnWakeUp(event);
}
}
@Override
public String toString() {
return "Child{" +
"name='" + name + "'}";
}
}
4.6 测试类
/**
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:29
*/
public class Test {
public static void main(String[] args) {
Child child = new Child("五条宝宝");
child.wakeUp();
}
}
5 扩展
5.1 对观察者注入的方式进行扩展思考(引入策略模式)
上述代码中有个缺陷,在Child中就提前加入了观察者,不是很灵活,当然可以在调用的时候手动传入,但是这样手写也不是很优雅,可以提前将组合策略写好,直接传入Child的有参构造中即可。
引入策略模式,管理观察者的组合方式,自由组合观察者
实现图
具体实现如下
5.1.1 Child(不再进行观察者的注册了,交给策略)
在有参构造中进行观察链的初始化赋值
/**
* 被观察者
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:22
*/
public class Child {
private String name;
public Child(String name) {
this.name = name;
}
public Child(String name, List<Observer> observers) {
this.name = name;
this.observers = observers;
}
private List<Observer> observers = new ArrayList<>();
public void wakeUp(){
Event event = new WakeUpEvent(System.currentTimeMillis(),"bed",this);
for (Observer observer : observers) {
observer.actionOnWakeUp(event);
}
}
@Override
public String toString() {
return "Child{" +
"name='" + name + "'}";
}
}
5.1.2 ObserverStrategy(策略接口)
/**
* 观察者策略
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:46
*/
public interface ObserverStrategy {
List<Observer> getObserverStrategy();
}
5.1.3 策略接口实现类
AllObserverStrategy(观察者Dad、Mum、Dog)
/**
* 观察者Dad、Mum、Dog
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:50
*/
public class AllObserverStrategy implements ObserverStrategy {
@Override
public List<Observer> getObserverStrategy() {
List<Observer> observers = new ArrayList<>();
observers.add(new Dad());
observers.add(new Mum());
observers.add(new Dog());
return observers;
}
}
DadAndDogStrategy(观察者Dad、Dog)
/**
* 观察者Dad、Dog
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:49
*/
public class DadAndDogStrategy implements ObserverStrategy {
@Override
public List<Observer> getObserverStrategy() {
List<Observer> observers = new ArrayList<>();
observers.add(new Dad());
observers.add(new Dog());
return observers;
}
}
DadAndMumStrategy(观察者Dad、Mum)
/**
* 观察者Dad、Mum
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:49
*/
public class DadAndMumStrategy implements ObserverStrategy {
@Override
public List<Observer> getObserverStrategy() {
List<Observer> observers = new ArrayList<>();
observers.add(new Dad());
observers.add(new Mum());
return observers;
}
}
MumAndDogStrategy(观察者Mum、Dog)
/**
* 观察者Mum、Dog
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:49
*/
public class MumAndDogStrategy implements ObserverStrategy {
@Override
public List<Observer> getObserverStrategy() {
List<Observer> observers = new ArrayList<>();
observers.add(new Mum());
observers.add(new Dog());
return observers;
}
}
5.1.4 Event(未修改,参考上述代码)
5.1.5 Observer(未修改,参考上述代码)
5.1.6 具体观察者(未修改,参考上述代码)
5.1.7 测试类
在创建被观察者对象的时候通过观察策略进行被观察者中观察链的赋值
/**
* @Author ChenJiahao(程序员五条)
* @Date 2021/9/11 15:29
*/
public class Test {
public static void main(String[] args) {
// 今天爸爸不在家,只有妈妈和狗狗可以作为观察者
Child child = new Child("五条宝宝",new MumAndDogStrategy().getObserverStrategy());
child.wakeUp();
// 今天妈妈不在家,只有爸爸和狗狗可以作为观察者
Child child1 = new Child("五条宝宝",new DadAndDogStrategy().getObserverStrategy());
child1.wakeUp();
// 今天狗狗出去玩了,只有爸爸和妈妈可以作为观察者
Child child2 = new Child("五条宝宝",new DadAndMumStrategy().getObserverStrategy());
child2.wakeUp();
// 今天都在家!!!
Child child3 = new Child("五条宝宝",new AllObserverStrategy().getObserverStrategy());
child3.wakeUp();
}
}
5.2 对触发方法的扩展思考
可以将wakeUp方法抽象成一个触发类,这样就方便后期的扩展了
在每个触发类中,可以灵活的去创建事件
在触发类中,应对监听者做一些判断,例如,需要哪些监听者就添加,不需要就不添加,而不是像上述代码一样,全部添加进监听链(5.1中解决了这个问题)
6 思维导图
7 示例源码地址
https://github.com/ChenJiahao0205/design-pattern/tree/master
最后
我是通过马士兵老师的视频和菜鸟教程学习的,部分内容可能会有雷同
想阅读更多设计模式相关文章,欢迎到我的专栏【设计模式学习笔记】、【设计模式】中去查看
在23篇设计模式文章发布完成之后,我会公开完整的思维导图,点关注,不迷路
感谢大家看到这里,文章如有不足,欢迎大家指出;彦祖点个赞吧彦祖点个赞吧彦祖点个赞吧,欢迎关注程序员五条!