模式定义
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式是一种对象行为模式。
模式结构
1、Subject(目标)
指被观察对象。在目标中定义了一个观察者集合,他可以存储任意数量的观察者对象,它提供一个接口来增加和删除观察者对象,同时它定义了的通知方法notify().目标类可以是借口,也可以是抽象类或实现类。
2、ConcreteSubject(具体目标)
是目标类的子类,通常它包含经常发生改变的数据,当它的状态发生改变时,向各个观察者发出通知。同时,若目标类中定义了抽象业务逻辑方法,则在其中将会被实现。
3、Object(观察者)
观察者将会对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update().又称抽象观察者模式。
4、ConcreteObserver(具体观察者)
在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;他实现了在抽象观察者Observer中定义的update方法。通常在实现时,可调用具体目标类的attach()方法将自己添加到目标类的观察者集合中或通过detach()方法将自己从集合中删除。
模式优缺点
优点
可以解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换;符合“开闭原则”
缺点
应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,可能导致系统崩溃。
模式的适用情况
1)一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中时他们可以独立的改变和复用。
2)一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象发生改变,可以降低耦合度。
3)一个对象必须通知其他对象,而并不知道这些对象是谁。
4)需要在系统中创建一个触发链,A的对象行为影响了B对象,B对象行为影响了C对象….
题目
某在线股票软件需要提供日下功能,当股票购买者所购买的某只股票价格变化幅动达到5%时,系统将自动发送通知(包括新价格)给购买该股票的股民,现使用观察者模式设计该系统,绘制类图并编程模拟实现。
思路构图
代码及结果
1、主要代码
(1)抽象目标类Shares,在其中定义了一个ArrayList类型的集合people,用于存储观察者对象,并定义了注册方法attach()和remove(),同时声明了抽象的通知方法notifyPeople().
public abstract class Shares {
protected ArrayList<SharesPeople> people = new ArrayList<SharesPeople>();
public void attach(SharesPeople sharespeople){
people.add(sharespeople);
}
public void remove(SharesPeople sharespeople){
people.remove(sharespeople);
}
public abstract void notifyPeople(int num);
}
(2)定义一个接口类型的抽象观察类者类SharesListener,在其中声明了抽象响应方法response()。
public interface SharesListener {
void response();
}
(3)具体目标类SharesEvent,是目标类Shares的子类,他实现了抽象方法notifyPeople(),在notifyPeople()中遍历了观察者集合,调用每一个观察者对象的response()响应方法。
public class SharesEvent extends Shares {
@Override
public void notifyPeople(int num) {
if(num>=5){
for(Object obj:people){
System.out.print("股票变化:");
((SharesPeople)obj).response();
}
}else{
System.out.print("股票变化:");
System.out.println("正常..");
}
}
}
(4)具体观察者类SharesPeople,实现了在抽象观察者重定义的响应方法response()。
public class SharesPeople implements SharesListener {
private String name;
public SharesPeople(String name){
this.name = name;
}
@Override
public void response() {
System.out.println("正在发送,通知股民成员:"+name+"。内容为:股票价格变化幅度达到5%..");
System.out.println("***"+name+"***"+"已收到通知");
}
}
2、测试代码
测试类Client
public class Client {
@Test
public void test(){
Shares shares = new SharesEvent();
SharesPeople people1 = new SharesPeople("易易");
SharesPeople people2 = new SharesPeople("舞舞");
SharesPeople people3 = new SharesPeople("大佬");
shares.attach(people1);
shares.attach(people2);
shares.attach(people3);
shares.notifyPeople(1);
shares.notifyPeople(2);
shares.notifyPeople(5);
}
}