设计模式学习笔记——观察者模式

观察者模式

观察者模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

结构图



代码实现

抽象观察者Observer:根据被观察者动作,做出相应动作。
/**
 * 抽象观察者类
 * @author xukai
 * 2016年3月16日 下午11:33:10
 */
public abstract class Observer {

	/**
	 * 做出相应
	 */
	public abstract void update();
	
}
抽象被观察者Subject:被观察,可以选择通过某个观察者,也可以不通知
/**
 * 抽象被观察者
 * @author xukai
 * 2016年3月16日 下午11:43:21
 */
public abstract class Subject {

	private Vector<Observer> observers = new Vector<>();
	

	public void attach(Observer observer){
		observers.add(observer);
	}
	
	public void detach(Observer observer){
		observers.remove(observer);
	}
	
	public void notifyObserver(){
		for(Observer o : observers){
			o.update();
		}
	}
	
}
具体被观察者ConcreteSubject:
/**
 * 具体被观察者
 * @author xukai
 * 2016年3月16日 下午11:46:37
 */
public class ConcreteSubject extends Subject {

	private String subjectState;

	public String getSubjectState() {
		return subjectState;
	}

	public void setSubjectState(String subjectState) {
		this.subjectState = subjectState;
	}

}
具体观察者ConcreteObserver:
/**
 * 具体观察者
 * 
 * @author xukai 2016年3月16日 下午11:37:20
 */
public class ConcreteObserver extends Observer {

	private String name;

	private String observerState;

	private ConcreteSubject subject;

	public ConcreteSubject getSubject() {
		return subject;
	}

	public void setSubject(ConcreteSubject subject) {
		this.subject = subject;
	}

	public ConcreteObserver(ConcreteSubject subject, String name) {
		this.subject = subject;
		this.name = name;
	}

	@Override
	public void update() {
		observerState = subject.getSubjectState();
		System.out.println("观察者"+ name +"的状态:" + observerState);
	}

}
客户端:
public class Client {

	public static void main(String[] args) {
		ConcreteSubject s = new ConcreteSubject();
		s.attach(new ConcreteObserver(s, "A"));
		s.attach(new ConcreteObserver(s, "B"));
		
		s.setSubjectState("ABC");
		s.notifyObserver();
	}
	
}
控制台:
观察者A的状态:ABC
观察者B的状态:ABC
可以看到根据被观察者的通知,可以修改观察者相应的信息。

demo

问题:公司中,老板有事外出,员工有的炒股,有的看NBA比赛,员工请求前台小妹通知老板回来。

结构图


代码实现

抽象通知者类Subject:
import java.util.Vector;

/**
 * 抽象通知者,即被观察者
 * 
 * @author xukai 2016年3月17日 上午9:40:26
 */
public abstract class Subject {

	protected String name;
	protected String state;

	public Subject(String name, String state) {
		this.name = name;
		this.state = state;
	}

	Vector<Observer> observers = new Vector<>();

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

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

	public void notifyObserver() {
		System.out.println(name + "说:" + state);
		for (Observer o : observers) {
			o.update();
		}
	}

}
抽象观察者类Observer:
/**
 * 抽象观察者,对通知者做出响应
 * 
 * @author xukai 2016年3月17日 上午9:39:03
 */
public abstract class Observer {

	private String name;

	protected Subject subject;

	protected String doing;

	public Observer(String name, Subject subject) {
		this.name = name;
		this.subject = subject;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void update();

	@Override
	public String toString() {
		return name + doing;
	}

}
具体通知者类Boss:
/**
 * 老板类,继承通知者
 * 
 * @author xukai 2016年3月17日 上午9:45:03
 */
public class Boss extends Subject {

	public Boss(String name, String state) {
		super(name, state);
	}

}
具体通知者类:
/**
 * 前台通知者
 * @author xukai
 * 2016年3月17日 上午10:25:47
 */
public class ReceptionGirl extends Subject {

	public ReceptionGirl(String name, String state) {
		super(name, state);
	}

}
看NBA的观察者:
/**
 * 具体观察者,喜爱看NBA
 * @author xukai
 * 2016年3月17日 上午9:57:21
 */
public class EmployeeNBAObserver extends Observer {

	public EmployeeNBAObserver(String name, Subject subject) {
		super(name, subject);
	}

	@Override
	public void update() {
		if(super.subject.state == "出去了"){
			super.doing = ",看NBA比赛...";
		}else if(super.subject.state == "回来了"){
			super.doing = ",停止看比赛,开始工作...";
		}
		System.out.println(super.getName() + super.doing);
	}

}
炒股的观察者:
/**
 * 具体观察者,喜爱看股票
 * @author xukai
 * 2016年3月17日 上午10:00:23
 */
public class EmployeeStockObserver extends Observer {

	public EmployeeStockObserver(String name, Subject subject) {
		super(name, subject);
	}

	@Override
	public void update() {
		if(super.subject.state == "出去了"){
			super.doing = ",看股票市场...";
		}else if(super.subject.state == "回来了"){
			super.doing = ",停止看股票,开始工作...";
		}
		System.out.println(super.getName() + super.doing);
	}

}
客户端:
public class TestObserver {

	public static void main(String[] args) {
		System.out.println("===========老板自己的行为通知==========");
		// 创建一个通知者
		Subject subject = new Boss("老板", "出去了");
		// 多个观察者
		Observer ob1 = new EmployeeNBAObserver("我爱看NBA", subject);
		Observer ob2 = new EmployeeStockObserver("我爱炒股", subject);
		
		// 通知者,添加观察者
		subject.attacth(ob1);
		subject.attacth(ob2);
		
		// 发出通知
		subject.notifyObserver();
		
		// 不通知炒股的人
		subject.detach(ob2);
		subject.state = "回来了";
		subject.notifyObserver();
		// 炒股的人还在炒股,被老板发现
		System.out.println(ob2 + "被老板发现在炒股");
		
		System.out.println("===========前台小妹通知老板回来==========");
		// 创建小妹
		subject = new ReceptionGirl("前台小妹", "出去了");
		// 多个观察者
		Observer ob3 = new EmployeeNBAObserver("我爱看NBA", subject);
		Observer ob4 = new EmployeeStockObserver("我爱炒股", subject);
		
		// 通知者,添加观察者
		subject.attacth(ob3);
		subject.attacth(ob4);
		
		// 发出通知
		subject.notifyObserver();
		
		subject.state = "回来了";
		subject.notifyObserver();
	}
	
}
控制台输出:

分析:
1.老板和前台小妹都是通知者
2.观察者需要知道老板的状态
3.通知者中使用Vector容器不使用List,是因为多线程操作时,Vector是安全地,而List是不安全的。

观察者模式优点

观察者与被观察者之间属于轻度的关联关系,并且是抽象耦合的,对于两者比较容易扩展。
观察者模式是一种常用的触发机制,形成一条触发链,依次对各个观察者的方法进行处理。但是由于链式触发,当观察者比较多的时候,性能问题很难解决。并且链式结构容易出现循环引用错误,造成系统假死。

使用场景

当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待给边,应该考虑使用观察者模式。
观察者模式所做的工作就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
另外,Java语言中,有接口Observer和它的实现类Observable,对观察者角色进行了实现。











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值