您的位置:首页 > 其它

设计模式->行为型模式->观察者模式

2017-06-13 22:33 316 查看
1.定义:又称订阅/发布模式,定义了对象间一种一对的的依赖关系,使得每当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新

该模式下行为的继承>类型的继承。抽象观察者和具体观察者之间属于行为继承

2.UML(推模式)



3.涉及角色
1.抽象主题(被观察者):含有抽象观察者的聚集,并实现了对该具体的操作主要涉及对观察者的删除/新增。管理观察者以及通知观察者。
2.抽象观察者:观察者接受到消息后具体的行为
3.具体主题:定义了具体被观察者的逻辑以及定义了哪些行为会被通知给观察者
4.具体观察者:抽象观察者的子类,接受消息后具体对消息的处理

4.优点

1.观察者和被观察者是抽象耦合,后续不管是扩展观察者还是被观察者都很方便,抽象主题持有抽象观察者的聚集

2.可以建立一套完整的观察机制。即被观察者也是观察者eg:前车司机及时观察者也是被观察者

3.广播机制。被观察者会向所有登记过的观察者发送信息

5.缺点

1.被观察者存在很多直接或者间接的观察者时,通知所有观察者会花费很多时间

2.被观察者之间存在循环依赖那么被观察者之间会循环调用有可能导致系统崩溃

3.java中的消息投递默认是顺序的,也就是说当一个观察者阻塞后,后影响后续的观察者执行,此时可以采用异步的方式,通过另外的线程进行异步投递,系统必须保证投递是以自恰的方式进行的

4.需要维护对象的一致性

6.使用场景

        1.关联行为场景,前提是行为可拆分

        2.对象改变时同时改变了其他的对象并且不知道有多少对象等待改变

3.跨系统之间的消息传递。其实可以使用JMS中间件

7.Code

//抽象主题

public abstract class Subject {

private List<Observer> observers = new ArrayList<Observer>();

public void addObserver(Observer observer) {
this.observers.add(observer);
}

public void removeObserver(Observer observer) {
this.observers.remove(observer);
}

public void nofityObserver(String status) {
for(Observer observer : this.observers) {
observer.update(status);
}
}
}
抽象观察者

public interface Observer {
public void update(String status);
}
具体主题

public class ConcreteSubject extends Subject {

private String status;

public String getStatus(){
return this.status;
}

public void changeStatus(String status) {
if(status.contains("A")) {
this.status = status.replaceAll("A", "B");
} else if(status.equalsIgnoreCase("B")) {
this.status = status.replaceAll("B", "A");
}

System.out.println("before status:" + status + ", after status:" + this.status);

this.nofityObserver(this.status);
}
}

具体观察者

public class ConcreteObserver implements Observer {

@Override
public void update(String status) {
System.out.println("status: " + status);
//TODO Business logic
}
}


客户端

public class Client {
public static void  main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();

subject.addObserver(observer);
subject.changeStatus("AAAAdf");
}
}


推模式存在如下问题

1.被登记的观察者都会被通知到,也就是说观察者有可能对该消息并不感兴趣。

2.观察者接受的消息和具体的当前的业务相关。

3.当业务需要扩展时,此时被观察者提供的数据无法满足新增业务

UML(拉模式)



和推模式相比区别在于:在推模式下发送给观察者的信息为具体的数据,即数据存在不完整性。拉模式下发送给观察者的信息为主题对象,数据信息完整,可能存在冗余

抽象主题

public abstract class Subject {

private List<Observer> observers = new ArrayList<Observer>();

public void addObserver(Observer observer) {
this.observers.add(observer);
}

public void removeObserver(Observer observer) {
this.observers.remove(observer);
}

public void nofityObserver(Subject subject) {
for(Observer observer : this.observers) {
observer.update(subject);
}
}
}
具体主题

public class ConcreteSubject extends Subject {

private String status;

public String getStatus(){
return this.status;
}

public void setStatus(String status) {
this.status = status;
}

public void changeStatus(String status) {
if(status.contains("A")) {
this.status = status.replaceAll("A", "B");
} else if(status.contains("B")) {
this.status = status.replaceAll("B", "A");
}

System.out.println("before status:" + status + ", after status:" + this.status);

this.nofityObserver(this);
}
}


抽象观察者

public interface Observer {
public void update(Subject subject);
}
具体观察者

public class ConcreteObserver implements Observer {

@Override
public void update(Subject subject) {
ConcreteSubject concreteSubject = (ConcreteSubject) subject;
String status = concreteSubject.getStatus();
if (status.contains("A")) {
//TODO Business logic
System.out.println("Support");
} else {
System.out.println("Not Support");
}
}
}


JDK中自带了观察者模式其中提供给我们的有主题(java.util.Observable)以及观察者(java.util.Oberver)其中主题为类,观察者为接口

针对主题类需要注意如下几个方法

1.protected void clearChanged():对象不再改变,或者已经将最新的改变通知给了所有注册的观察者,hasChanged()将返回false

2.boolean hasChange():测试对象是否改变

3.void nofityObservers(Object arg):如果hasChanged方法指示的对象已经改变,则通知所有注册的观察者并调用clearChanged方法指示对象不再改变

4.protected
void setChanged():标记主题对象已经改变,hasChange()将返回true

参见上面Observable类的notifyObservers(Object
arg)方法,hasChanged()为true才会通知观察者数据有变化,并且在通知完成之后调用clearChanged()修改hasChanged()为false,所以当主题数据改变时,需要先调用setChanged()方法使hasChanged为true

Code:

主题

public class MyObservable extends Observable {

public void output(String arg) {
this.setChanged();//固定模式,具体主题必须要预先调用该方法
this.notifyObservers(arg);
}
}

观察者

public class MyObserver implements Observer {
private Observable observable = null;

public MyObserver(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}

@Override
public void update(Observable o, Object arg) {
System.out.println("Test String:" + arg);
}
}客户端
public class Client {
public static void main(String[] args) {
MyObservable observable = new MyObservable();

MyObserver myObserver = new MyObserver(observable);
observable.output("AAAA");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: