23种设计模式
观察者模式是经典设计模式中的一种,使用广泛。
观察者模式实现两个耦合度较高的类解耦。
观察者模式由观察者和被观察者组成;在实现中,被观察者为主体;在作用中,观察者为主体。(一般情况下)
观察者模式在现实中的场景可简单对应为:张三看见李四去吃饭了,张三也去吃饭了。
张三是观察者,李四是被观察者。
李四去吃饭,被观察者的状态改变;张三看见,被观察者广播通知观察者;张三也去吃饭了,执行观察者自身动作。
通过这个例子,可以理解到,被观察者需要作出三件事:
- 被观察者需要添加观察者到自身广播范围(张三需要能看见李四);
- 被观察者需要删除观察者从自身广播范围(张三有时候不要看李四去吃饭,可能不看他了);
- 被观察者需要进行广播通知范围内的观察者。
观察者就只需要做一件事:
当被通知时,执行自身的动作。
接下来是实现的一个小例子:
首先需要定义观察者和被观察者的行为(接口)
定义被观察者的接口IObservered
方法
addObserver(ObserveredPeople o)
modify(Object arg)
delObserver(ObserveredPeople o)
public interface IObservered {
boolean addObserver(IObserver o);
void modifyObserver(Object arg);
boolean delObserver(IObserver o);
}
定义观察者的接口IObserver
方法update()
public interface IObserver {
void update(ObserveredPeople o,Object arg);
}
定义被观察者的实现类
ObserveredPeople
public class ObserveredPeople implements IObservered{
private boolean changed;//通知标志,true才通知
private Vector vector;//观察者广播范围
public void setChanged(){
changed = true;
}
public ObserveredPeople(){
//构造方法中进行实例化和初始化
changed = false;
vector = new Vector();
}
@Override
public boolean addObserver(IObserver o) {
//如果传入对象为空,或者广播范围内已存在
//那么就会抛出空指针异常
//可以在外层捕获这个异常
if(o != null && !vector.contains(o)){
vector.addElement(o);
return true;
}else{
throw new NullPointerException("传入的观察者对象空");
}
}
@Override
public void modifyObserver(Object arg) {
//如果有效,使用增强for语句循环调用update方法
if(changed){
for (Object o : vector) {
if(o instanceof IObserver){
((IObserver) o).update(this, arg);
}
}
}
changed = false;
}
@Override
public boolean delObserver(IObserver o) {
if(o != null && vector.contains(o)){
vector.remove(o);
return true;
}else{
throw new NullPointerException("传入的观察者不存在或者不在广播范围内");
}
}
}
以上这些类可以作为工具类存在,也就是说,在任何地方能够使用到观察者模式,这些都是相同的。
具体使用观察者实现观察者接口,被观察者继承被观察者类。
创建一个被观察者
//注意导包
public class ObserveredUsing extends ObserveredPeople{
private String name;
private int age;
public ObserveredUsing(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setData(Object arg){
System.out.println("name:"+name+" "+"age:"+age+" "+"arg:"+arg.toString());
modifyObserver(arg);
}
}
创建2个观察者
//注意导包
public class ObserverUsingEat implements IObserver{
private String name;
private int age;
public ObserverUsingEat(String name,int age){
this.name = name;
this.age = age;
}
@Override
public void update(ObserveredPeople o, Object arg) {
System.out.println("name:"+name+" "+"age:"+age+" "+"arg:"+arg.toString());
}
}
第二个观察者
public class ObserverUsingPlay implements IObserver{
private String name;
private String play;
public ObserverUsingPlay(String name,String play){
this.name = name;
this.play = play;
}
private void doPlay(){
System.out.println("开始运动");
System.out.println("name:"+name);
System.out.print(" 我做"+play+"运动");
}
@Override
public void update(ObserveredPeople o, Object arg) {
doPlay();
System.out.println(arg.toString());
}
}
主方法
public class Main {
public static void main(String[] args) {
/**
* 张三是被观察者
*/
ObserveredUsing zhangsan = new ObserveredUsing("张三",32);
/**
* 李四,王五是观察者
* 当张三做出动作,李四王五会做出相应的动作
*/
ObserverUsingEat lisi = new ObserverUsingEat("李四",20);
ObserverUsingEat wangwu = new ObserverUsingEat("王五",80);
/**
* 添加到广播对象中
*/
ObserverUsingPlay no1 = new ObserverUsingPlay("1号", "跑步");
ObserverUsingPlay no2 = new ObserverUsingPlay("2号", "跳");
zhangsan.addObserver(lisi);
zhangsan.addObserver(wangwu);
zhangsan.addObserver(no1);
zhangsan.addObserver(no2);
zhangsan.setChanged();
zhangsan.setData("吃饭");
}
}
运行结果
name:张三 age:32 arg:吃饭
name:李四 age:20 arg:吃饭
name:王五 age:80 arg:吃饭
开始运动
name:1号
我做跑步运动吃饭
开始运动
name:2号
我做跳运动吃饭
这个代码和jdk实现的源码基本类似,但是jdk的是线程安全的,我们这个线程不安全。
使用观察者模式一般使用jdk的接口和类,非常容易使用。
但是自己写一次,理解更加深刻。
23种设计模式