观察者模式
- 1.什么是观察者模式
- 2.观察者模式的角色
- 3.实现方式
- 4.分析观察者模式
- 5.例子
- 5.1 结构图
- 5.2 抽象的观察者
- 5.3 抽象的被观察者
- 5.4 具体的观察者
- 5.5 具体的被观察者
- 5.6 测试
- 5.7 结果
- 6.总结
- 7.扩展
- 7.1 委托接口
- 7.2 让抽象的被观察者实现委托接口
- 7.3 具体的委托类
- 7.4 测试
- 7.5 结果
23种设计模式
1.什么是观察者模式
观察者模式在现实中非常的常见。
中午了,小李第一个去吃饭,小张看见小李去吃饭了,小张放下自己的工作,也去吃饭了。其他人看到小张去吃饭了(或者小李),于是大家都去吃饭了。可怜小王没看到吃饭的任何人,在大家吃饭的时候,小王还在工作。
观察者模式就是一个状态发生改变,会引发另一个执行动作。
解释一下:
小李第一个去吃饭——-被观察者状态发生改变
被观察者需要广播通知自己的观察者列表中的对象
小张看见小李——-被观察者广播列表中含有自己这个观察者
小张看见小李去吃饭——–被观察者广播自己的观察者列表
小张也去吃饭———观察者收到通知,执行自己的方法
小王没看到任何人——–作为观察者,没有被任何被观察者加入广播列表
所以,被观察者广播自己的观察者时,没有被观察者通知小王。
小王还在工作——-观察者不知道被观察者的状态改变,也没有执行自己的收到通知的方法。
2.观察者模式的角色
Subject(抽象的被观察者)
ConcreteSubject(具体的被观察者)
Observer(抽象的观察者)
ConcreteObserver(具体的观察者)
3.实现方式
首先对于观察者模式来说,在功能上,观察者收到通知后执行的方法一般是核心;在实现上,被观察者广播通知观察者是核心。
所以:
抽象的观察者一般用接口实现。
具体的观察者实现抽象的观察者的接口。
抽象的被观察者一般用抽象类实现。
具体的被观察者继承抽象的被观察者。
4.分析观察者模式
经过以上分析大致可以得到观察者模式中抽象的角色应该定义的方法了。
对于观察者,因为受到通知后会执行一个方法,而且这个方法对于被观察者是可见的(方法被动调用—–任何方法只有发起调用才会执行,没有发起调用,不会执行任何方法)
对于被观察者需要把观察者加入到广播列表,所以要有列表,有增加的方法。有增加的方法必然有删除的方法。
被观察者状态改变,所以有一个变量用来记录被观察者的状态
同时有一个方法来改变被观察者状态。
5.例子
5.1 结构图
5.2 抽象的观察者
package observer.abs;
import subject.abs.Subj;
public interface Obser {
void update(Subj subj,Object arg);
}
5.3 抽象的被观察者
package subject.abs;
import java.util.ArrayList;
import java.util.List;
import observer.abs.Obser;
public abstract class Subj{
protected List<Obser> obsers = new ArrayList<Obser>();
protected Boolean change = Boolean.FALSE;
public abstract void addObser(Obser obser);
public abstract void delObser(Obser obser);
public void setChange(Object arg){
change = Boolean.TRUE;
broadcast(arg);
change = Boolean.FALSE;
}
private void broadcast(Object arg){
if(change){
for(Obser obser : obsers){
obser.update(this, arg);
}
}
}
public void delAll(){
for(Obser obser : obsers){
delObser(obser);
}
}
}
5.4 具体的观察者
package observer.impl;
import observer.abs.Obser;
import subject.abs.Subj;
public class Obser1 implements Obser{
@Override
public void update(Subj subj, Object arg) {
System.out.println("Obser1执行了updata的方法:"+arg.toString());
}
}
package observer.impl;
import observer.abs.Obser;
import subject.abs.Subj;
public class Obser2 implements Obser{
@Override
public void update(Subj subj, Object arg) {
System.out.println("Obser2执行了updata的方法:"+arg.toString());
}
}
5.5 具体的被观察者
package subject.impl;
import observer.abs.Obser;
import subject.abs.Subj;
public class Subj1 extends Subj{
@Override
public void addObser(Obser obser) {
System.out.println("Subj1#add"+obser.toString());
if(obser != null && !super.obsers.contains(obser)){
super.obsers.add(obser);
}
}
@Override
public void delObser(Obser obser) {
System.out.println("Subj1#del"+obser.toString());
super.obsers.remove(obser);
}
}
package subject.impl;
import observer.abs.Obser;
import subject.abs.Subj;
public class Subj2 extends Subj{
@Override
public void addObser(Obser obser) {
System.out.println("Subj2#add"+obser.toString());
super.obsers.add(obser);
}
@Override
public void delObser(Obser obser) {
System.out.println("Subj2#del"+obser.toString());
super.obsers.remove(obser);
}
}
5.6 测试
package client;
import bridge.impl.Bridge1;
import observer.impl.Obser1;
import observer.impl.Obser2;
import subject.impl.Subj1;
import subject.impl.Subj2;
public class Main {
public static void main(String[] args) {
//被观察者
Subj1 subj1 = new Subj1();
//观察者
Obser1 obser1 = new Obser1();
//被观察者增加观察者到广播列表
subj1.addObser(obser1);
//被观察者状态发生改变
subj1.setChange("被观察者状态改变");
//新增另一个观察者
Obser1 obser12 = new Obser1();
//被观察者增加到广播列表
subj1.addObser(obser12);
//被观察者状态改变
subj1.setChange("我增加了一个人到自己的广播列表");
//删除一个观察者
subj1.delObser(obser12);
//被观察者状态改变
subj1.setChange("我删除了一个人");
//新增另一类观察者
Obser2 obser2 = new Obser2();
//增加到被观察者广播列表
subj1.addObser(obser2);
//被观察者状态改变
subj1.setChange("我增加了另一种观察者");
//新增另一类被观察者
Subj2 subj2 = new Subj2();
//被观察者增加观察者到广播列表
subj2.addObser(obser1);
subj2.addObser(obser2);
//观察者状态改变
subj2.setChange("我是第二种观察者");
// //委托解决观察者模式被观察者需要继承实现的弊端
// Bridge1 bridge1 = new Bridge1(subj1);
// //此时bridge1就是被观察者1,但是bridge1类没有继承任何类
// bridge1.delAll();
// bridge1.addObser(obser1);
// bridge1.addObser(obser2);
// bridge1.setChange("我是委托");
// bridge1.delObser(obser1);
// bridge1.addObser(obser12);
// bridge1.setChange("我是委托的操作");
}
}
5.7 结果
Subj1#addobserver.impl.Obser1@1f33675
Obser1执行了updata的方法:被观察者状态改变
Subj1#addobserver.impl.Obser1@1690726
Obser1执行了updata的方法:我增加了一个人到自己的广播列表
Obser1执行了updata的方法:我增加了一个人到自己的广播列表
Subj1#delobserver.impl.Obser1@1690726
Obser1执行了updata的方法:我删除了一个人
Subj1#addobserver.impl.Obser2@9931f5
Obser1执行了updata的方法:我增加了另一种观察者
Obser2执行了updata的方法:我增加了另一种观察者
Subj2#addobserver.impl.Obser1@1f33675
Subj2#addobserver.impl.Obser2@9931f5
Obser1执行了updata的方法:我是第二种观察者
Obser2执行了updata的方法:我是第二种观察者
6.总结
观察者模式对于观察者比较友好,非常的好用,只需要实现接口即可。
但是对于被观察者来说,要实现被观察者必须继承类,而Java又是单继承的机制,所以就会浪费继承。
解决方式—–使用委托。
新增一个中间类,让中间类关联被观察者类,那么中间类不仅可以继承,同时也是被观察者的持有者,可以调用被观察者的所有方法。
如果只调用被观察者的对外方法,那么完全可以把中间类当做被观察者。
采用模板模式,可以让一个委托类可以委托所有的被观察者,只需要让被观察者实现委托类的接口,那么对于委托类和抽象的被观察者来说,他们实现了同样的接口。
所以当具体的委托类持有委托类的接口对象时,自然可以持有所有的被观察者。
7.扩展
7.1 委托接口
注意委托接口应该与被观察者抽象类中对外方法完全相同的定义。
package bridge.abs;
import observer.abs.Obser;
public interface Bridge {
void addObser(Obser obser);
void delObser(Obser obser);
void setChange(Object arg);
void delAll();
}
7.2 让抽象的被观察者实现委托接口
package subject.abs;
import java.util.ArrayList;
import java.util.List;
import bridge.abs.Bridge;
import observer.abs.Obser;
public abstract class Subj implements Bridge{
protected List<Obser> obsers = new ArrayList<Obser>();
protected Boolean change = Boolean.FALSE;
public abstract void addObser(Obser obser);
public abstract void delObser(Obser obser);
public void setChange(Object arg){
change = Boolean.TRUE;
broadcast(arg);
change = Boolean.FALSE;
}
private void broadcast(Object arg){
if(change){
for(Obser obser : obsers){
obser.update(this, arg);
}
}
}
public void delAll(){
for(Obser obser : obsers){
delObser(obser);
}
}
}
不用修改任何方法,只需要添加关键字和委托接口
7.3 具体的委托类
package bridge.impl;
import observer.abs.Obser;
import bridge.abs.Bridge;
public class Bridge1 implements Bridge{
private Bridge bridge;
public Bridge1(Bridge bridge) {
this.bridge = bridge;
}
@Override
public void addObser(Obser obser) {
bridge.addObser(obser);
}
@Override
public void delObser(Obser obser) {
bridge.delObser(obser);
}
@Override
public void setChange(Object arg) {
bridge.setChange(arg);
}
@Override
public void delAll() {
bridge.delAll();
}
}
7.4 测试
package client;
import bridge.impl.Bridge1;
import observer.impl.Obser1;
import observer.impl.Obser2;
import subject.impl.Subj1;
import subject.impl.Subj2;
public class Main {
public static void main(String[] args) {
//被观察者
Subj1 subj1 = new Subj1();
//观察者
Obser1 obser1 = new Obser1();
//被观察者增加观察者到广播列表
subj1.addObser(obser1);
//被观察者状态发生改变
subj1.setChange("被观察者状态改变");
//新增另一个观察者
Obser1 obser12 = new Obser1();
//被观察者增加到广播列表
subj1.addObser(obser12);
//被观察者状态改变
subj1.setChange("我增加了一个人到自己的广播列表");
//删除一个观察者
subj1.delObser(obser12);
//被观察者状态改变
subj1.setChange("我删除了一个人");
//新增另一类观察者
Obser2 obser2 = new Obser2();
//增加到被观察者广播列表
subj1.addObser(obser2);
//被观察者状态改变
subj1.setChange("我增加了另一种观察者");
//新增另一类被观察者
Subj2 subj2 = new Subj2();
//被观察者增加观察者到广播列表
subj2.addObser(obser1);
subj2.addObser(obser2);
//观察者状态改变
subj2.setChange("我是第二种观察者");
//委托解决观察者模式被观察者需要继承实现的弊端
Bridge1 bridge1 = new Bridge1(subj1);
//此时bridge1就是被观察者1,但是bridge1类没有继承任何类
bridge1.delAll();
bridge1.addObser(obser1);
bridge1.addObser(obser2);
bridge1.setChange("我是委托");
bridge1.delObser(obser1);
bridge1.addObser(obser12);
bridge1.setChange("我是委托的操作");
}
}
7.5 结果
Subj1#addobserver.impl.Obser1@1f33675
Obser1执行了updata的方法:被观察者状态改变
Subj1#addobserver.impl.Obser1@1690726
Obser1执行了updata的方法:我增加了一个人到自己的广播列表
Obser1执行了updata的方法:我增加了一个人到自己的广播列表
Subj1#delobserver.impl.Obser1@1690726
Obser1执行了updata的方法:我删除了一个人
Subj1#addobserver.impl.Obser2@9931f5
Obser1执行了updata的方法:我增加了另一种观察者
Obser2执行了updata的方法:我增加了另一种观察者
Subj2#addobserver.impl.Obser1@1f33675
Subj2#addobserver.impl.Obser2@9931f5
Obser1执行了updata的方法:我是第二种观察者
Obser2执行了updata的方法:我是第二种观察者
Subj1#delobserver.impl.Obser1@1f33675
Subj1#addobserver.impl.Obser1@1f33675
Subj1#addobserver.impl.Obser2@9931f5
Obser2执行了updata的方法:我是委托
Obser1执行了updata的方法:我是委托
Subj1#delobserver.impl.Obser1@1f33675
Subj1#addobserver.impl.Obser1@1690726
Obser2执行了updata的方法:我是委托的操作
Obser1执行了updata的方法:我是委托的操作
23种设计模式