一、什么是观察者模式(Observer模式或观察——订阅模式)
定义对象间一种一对多的依赖关系,当一个对象的类发生改变时,所有依赖于它的对象都得到通知并自动更新。
1.目的
在各个类协作一致的基础上低耦合,提高代码复用率。
2.关键对象
目标(subject) 对象(observer),一个目标可有多个观察者,一个观察者也可以有多个观察目标。一旦目标的状态发生改变,所有的观察者都得到通知。
3.使用条件
(1)一个对象发生改变时需要通知其他对象
(2)一个对象必须通知其他对象,而它又不能假定其他对象是谁(互相不知道对方存在而表现地似乎知道),对象之间的低耦合。
(3)一个抽象模型有两个方面,其中一方面依赖于另一方面,将这两者封装在独立的对象中可以使它们各自独立地改变和复用。
二、观察者模式的结构
Subject 观察目标
——提供注册删除观察对象的接口
——通知观察对象
Observer 观察对象
——观察目标发生改变时为具体的观察对象提供统一的更新接口
ConcreteSubject 具体目标
——在观察对象那里存入具体状态
——当它的状态改变时,向它的各个观察者发出通知
ConcreteObserver 具体观察者
——更新接口使自身状态和目标状态一致
——维护一个指向ConcreteObserver的引用,存储相关状态
三、优缺点
1.目标和观察者之间的抽象耦合
一个目标所知道的仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。不知道任何一个观察者属于哪个具体的类,这样目标和观察者之间的耦合程度是最小的
2.支持广播通信
3.错误的更新
四、具体示例
示例1.
观察者:
package patterns.myobserver;
public interface Observer {
void update();
}
package patterns.myobserver;
public class ConcreteObserver implements Observer{
String status;
String name;
ConcreteSubject Subject;
public ConcreteObserver(String name,Subject subject) {
this.name = name;
this.Subject = (ConcreteSubject) subject;
//this.Subject.registerObserver(this);
}
public void update() {
status = Subject.getStatus();
System.out.println(name+"状态更新:"+status);
}
}
观察对象:
package patterns.myobserver;
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObserver();
}
package patterns.myobserver;
import java.util.ArrayList;
public class ConcreteSubject implements Subject{
String ConcreteSubject;
String status;
public ConcreteSubject(String status) {
super();
this.status = status;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
notifyObserver();
}
ArrayList<Observer> List = new ArrayList<>();
public void registerObserver(Observer o) {
List.add(o);
}
public void removeObserver(Observer o) {
List.remove(o);
}
public void notifyObserver() {
for(Observer u:List)
{
u.update();
}
}
}
客户端:
package patterns.myobserver;
public class ClientTest {
public static void main(String[] args) {
Subject boss = new ConcreteSubject("老板来了");
Subject delivery = new ConcreteSubject("快递到了");
Observer user = new ConcreteObserver("用户",boss);
Observer palyer = new ConcreteObserver("玩家",delivery);
boss.registerObserver(user);
boss.notifyObserver();
delivery.registerObserver(palyer);
delivery.notifyObserver();
}
}
运行结果:
示例2.
假设一个场景,当老板进入办公室,办公室的所有用户会接受到“老板来了!” 的信息,而快递到了的时候,用户和玩家都接收到“快递到了!”的信息。
接口,抽象观察对象和抽象观察者
package patterns.observer;
public interface Subject {
void notifyTo();
void register(Observer u);
}
package patterns.observer;
public interface Observer {
void update(String status);
}
package patterns.observer;
import java.util.ArrayList;
public class BossCome implements Subject{
String status;
ArrayList<Observer> userList = new ArrayList<>();
public BossCome(String status) {
super();
this.status = status;
}
public void register(Observer u)
{
userList.add(u);
}
public void notifyTo()
{
for(Observer u:userList)
{
u.update(status);
}
}
}
具体观察对象:快递、老板
package patterns.observer;
import java.util.ArrayList;
public class Delivery implements Subject{
String status;//快递
ArrayList<Observer> userList = new ArrayList<>();
public Delivery(String status) {
this.status = status;
}
public void register(Observer u)
{
userList.add(u);
}
public void notifyTo()
{
for(Observer u:userList)
{
u.update(status);
}
}
}
具体观察者:玩家、用户
package patterns.observer;
public class Players implements Observer{
String name;
public Players(String name) {
super();
this.name = name;
}
public void update(String status) {
System.out.println("玩家"+this.name+status);
}
}
package patterns.observer;
public class User implements Observer{
String name;
public User(String name) {
super();
this.name = name;
}
public void update(String status) {
System.out.println("用户"+this.name+status);
}
}
package patterns.observer;
public class ClientTest {
public static void main(String[] args) {
Observer tony = new User("Tony");
Observer tom = new Players("Tom");
Delivery d = new Delivery("快递到了");
BossCome g = new BossCome("老板来了");
d.register(tony);
d.register(tom);
d.notifyTo();
g.register(tom);
g.notifyTo();
}
}
运行结果:
本博客资料、代码来源于设计模式[Design_Pattern]可复用面向对象的软件的基础和网络,课上教学等,本博客仅用于个人学习,可能存在纰漏,敬请批评指正。