28 【行为型模式】观察者模式

2018-01-21  本文已影响2人  猿笔记

定义

  观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

结构图


要素
● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
● ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。
import java.util.*;  
abstract class Subject {  
    //定义一个观察者集合用于存储所有观察者对象  
protected ArrayList observers<Observer> = new ArrayList();  
  
//注册方法,用于向观察者集合中增加一个观察者  
    public void attach(Observer observer) {  
    observers.add(observer);  
}  
  
    //注销方法,用于在观察者集合中删除一个观察者  
    public void detach(Observer observer) {  
    observers.remove(observer);  
}  
  
    //声明抽象通知方法  
    public abstract void notify();  
}  

class ConcreteSubject extends Subject {  
    //实现通知方法  
    public void notify() {  
        //遍历观察者集合,调用每一个观察者的响应方法  
        for(Object obs:observers) {  
            ((Observer)obs).update();  
        }  
    }     
}  

interface Observer {  
    //声明响应方法  
    public void update();  
}  

class ConcreteObserver implements Observer {  
    //实现响应方法  
    public void update() {  
        //具体响应代码  
    }  
} 

示例

  多人联机对战游戏


import java.util.*;  
  
//抽象观察类  
interface Observer {  
    public String getName();  
    public void setName(String name);  
    public void help(); //声明支援盟友方法  
    public void beAttacked(AllyControlCenter acc); //声明遭受攻击方法  
}  
  
//战队成员类:具体观察者类  
class Player implements Observer {  
    private String name;  
  
    public Player(String name) {  
        this.name = name;  
    }  
      
    public void setName(String name) {  
        this.name = name;  
    }  
      
    public String getName() {  
        return this.name;  
    }  
      
    //支援盟友方法的实现  
    public void help() {  
        System.out.println("坚持住," + this.name + "来救你!");  
    }  
      
    //遭受攻击方法的实现,当遭受攻击时将调用战队控制中心类的通知方法notifyObserver()来通知盟友  
    public void beAttacked(AllyControlCenter acc) {  
        System.out.println(this.name + "被攻击!");  
        acc.notifyObserver(name);         
    }  
}  
  
//战队控制中心类:目标类  
abstract class AllyControlCenter {  
    protected String allyName; //战队名称  
    protected ArrayList<Observer> players = new ArrayList<Observer>(); //定义一个集合用于存储战队成员  
      
    public void setAllyName(String allyName) {  
        this.allyName = allyName;  
    }  
      
    public String getAllyName() {  
        return this.allyName;  
    }  
      
    //注册方法  
    public void join(Observer obs) {  
        System.out.println(obs.getName() + "加入" + this.allyName + "战队!");  
        players.add(obs);  
    }  
      
    //注销方法  
    public void quit(Observer obs) {  
        System.out.println(obs.getName() + "退出" + this.allyName + "战队!");  
        players.remove(obs);  
    }  
      
    //声明抽象通知方法  
    public abstract void notifyObserver(String name);  
}  
  
//具体战队控制中心类:具体目标类  
class ConcreteAllyControlCenter extends AllyControlCenter {  
    public ConcreteAllyControlCenter(String allyName) {  
        System.out.println(allyName + "战队组建成功!");  
        System.out.println("----------------------------");  
        this.allyName = allyName;  
    }  
      
    //实现通知方法  
    public void notifyObserver(String name) {  
        System.out.println(this.allyName + "战队紧急通知,盟友" + name + "遭受敌人攻击!");  
        //遍历观察者集合,调用每一个盟友(自己除外)的支援方法  
        for(Object obs : players) {  
            if (!((Observer)obs).getName().equalsIgnoreCase(name)) {  
                ((Observer)obs).help();  
            }  
        }         
    }  
}  

class Client {  
    public static void main(String args[]) {  
        //定义观察目标对象  
AllyControlCenter acc;  
        acc = new ConcreteAllyControlCenter("金庸群侠");  
          
        //定义四个观察者对象  
        Observer player1,player2,player3,player4;  
          
        player1 = new Player("杨过");  
        acc.join(player1);  
          
        player2 = new Player("令狐冲");  
        acc.join(player2);  
          
        player3 = new Player("张无忌");  
        acc.join(player3);  
          
        player4 = new Player("段誉");  
        acc.join(player4);  
          
        //某成员遭受攻击  
        Player1.beAttacked(acc);  
    }  
}  

扩展:MVC

总结

适用场景

(1) 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
(2) 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
(3) 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制

上一篇 下一篇

猜你喜欢

热点阅读