设计模式--观察者模式

1. 概述

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

2. 解决的问题

  将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。

3. 模式中的角色

  3.1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

  3.2 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

  3.3 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

  3.4 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

4. 模式解读

  4.1 观察者模式的代码

 1  /// <summary>
 2     /// 抽象主题类
 3     /// </summary>
 4     public abstract class Subject
 5     {
 6         private IList<Observer> observers = new List<Observer>();
 7 
 8         /// <summary>
 9         /// 增加观察者
10         /// </summary>
11         /// <param name="observer"></param>
12         public void Attach(Observer observer)
13         {
14             observers.Add(observer);
15         }
16 
17         /// <summary>
18         /// 移除观察者
19         /// </summary>
20         /// <param name="observer"></param>
21         public void Detach(Observer observer)
22         {
23             observers.Remove(observer);
24         }
25 
26         /// <summary>
27         /// 向观察者(们)发出通知
28         /// </summary>
29         public void Notify()
30         {
31             foreach (Observer o in observers)
32             {
33                 o.Update();
34             }
35         }
36     }
37 
38     /// <summary>
39     /// 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己
40     /// </summary>
41     public abstract class Observer
42     {
43         public abstract void Update();
44     }
45 
46     /// <summary>
47     /// 具体观察者或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
48     /// </summary>
49     public class ConcreteSubject : Subject
50     {
51         private string subjectState;
52 
53         /// <summary>
54         /// 具体观察者的状态
55         /// </summary>
56         public string SubjectState
57         {
58             get { return subjectState; }
59             set { subjectState = value; }
60         }
61     }
62 
63     /// <summary>
64     /// 具体观察者,实现抽象观察者角色所要求的更新接口,已是本身状态与主题状态相协调
65     /// </summary>
66     public class ConcreteObserver : Observer
67     {
68         private string observerState;
69         private string name;
70         private ConcreteSubject subject;
71 
72         /// <summary>
73         /// 具体观察者用一个具体主题来实现
74         /// </summary>
75         public ConcreteSubject Subject
76         {
77             get { return subject; }
78             set { subject = value; }
79         }
80 
81         public ConcreteObserver(ConcreteSubject subject, string name)
82         {
83             this.subject = subject;
84             this.name = name;
85         }
86 
87         /// <summary>
88         /// 实现抽象观察者中的更新操作
89         /// </summary>
90         public override void Update()
91         {
92             observerState = subject.SubjectState;
93             Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
94         }
95     }

  4.2 客户端代码

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             // 具体主题角色通常用具体自来来实现
 6             ConcreteSubject subject = new ConcreteSubject();
 7 
 8             subject.Attach(new ConcreteObserver(subject, "Observer A"));
 9             subject.Attach(new ConcreteObserver(subject, "Observer B"));
10             subject.Attach(new ConcreteObserver(subject, "Observer C"));
11 
12             subject.SubjectState = "Ready";
13             subject.Notify();
14 
15             Console.Read();
16         }
17     }

 


以上内容来源于网络,下面是我在实际应用中的例子:

公司的一个需求,具体是,我的一个类变化了,我需要了解到这个类的变化,并且得到他的id,和模块名称(在本demo中没有体现),那么就用到了观察者模式!

首先,我们的业务类有一个顶层的接口,所有的业务类都实现了这个接口

package com.sun.Observer;

import java.io.Serializable;

public interface Entity<PK extends Serializable> extends Serializable {

    void setId(PK id);

    PK getId();
}

 定义一个具体的业务类,方便测试

package com.sun.Observer;

public class Student implements Entity<String> {

    private static final long serialVersionUID = 1L;
    private String id;
    private String name;
    private Integer age;

    @Override
    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

 定义一个观察者

package com.sun.Observer;

import java.util.Observable;
import java.util.Observer;

public class TstObServer implements Observer{
    
    @Override
    public void update(Observable observ, java.lang.Object o) {
        EntityEventBlock eeb = (EntityEventBlock) observ;
        System.out.println("捕获业务对象变动数 = "+ eeb.getChangeEvents().size());
        for (EntityChangeEvent event : eeb.getChangeEvents()) {
            System.out.println("entityCls:[" + event.getEntityCls() + "]"
                    + ",id:[" + event.getId() + "]"
                    + ",变动类型:[" + (event.getType() == EntityChangeEvent.TYPE_ADD ? "新增" :
                            event.getType() == EntityChangeEvent.TYPE_UPDATE ? "更新" :
                            event.getType() == EntityChangeEvent.TYPE_DELETE ? "删除" : "") + "]");
        }
    }

}

 监听实体变化的辅助类

package com.sun.Observer;

import java.io.Serializable;

import org.apache.commons.lang3.StringUtils;

public class EntityChangeEvent {
    public static final int TYPE_ADD = 1;
    public static final int TYPE_UPDATE = 2;
    public static final int TYPE_DELETE = 3;

    private Class<?> entityCls;
    private Serializable id;
    private int type;

    public EntityChangeEvent(Class<?> entityCls, Serializable id, int type) {
        this.id = id;
        this.type = type;
        this.entityCls = entityCls;
    }

    public Class<?> getEntityCls() {
        return entityCls;
    }

    public Serializable getId() {
        return id;
    }

    public String getIdStr() {
        return id != null ? id.toString() : null;
    }

    public void setId(Serializable id) {
        this.id = id;
    }

    public int getType() {
        return type;
    }

    @Override
    public boolean equals(Object obj) {
        if (!EntityChangeEvent.class.isInstance(obj)) {
            return false;
        }
        EntityChangeEvent otherObj = (EntityChangeEvent) obj;
        return (StringUtils.equals(getIdStr(), otherObj.getIdStr()));
    }

    @Override
    public int hashCode() {
        if (id != null) {
            return id.hashCode();
        }
        return super.hashCode();
    }

}

通知主题

 1 package com.sun.Observer;
 2 
 3 import java.io.Serializable;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 import java.util.Observable;
 7 import java.util.Observer;
 8 
 9 public class EntityEventBlock extends Observable {
10     private List<EntityChangeEvent> changeEvents = new ArrayList<EntityChangeEvent>();
11 
12     public void setObservers(List<Observer> observers) {//这里可以注入进来observer
13         for (Observer observer : observers) {
14             this.addObserver(observer);
15         }
16     }
17 
18     public static synchronized EntityEventBlock instance() {
19         EntityEventBlock eventBlock = new EntityEventBlock();// from httpSession
20         return eventBlock;
21     }
22 
23     public void makeDelEvent(Class entityCls, Serializable id) {
24         makeChangeEvent(entityCls, id, EntityChangeEvent.TYPE_DELETE);
25     }
26 
27     public void makeAddEvent(Class entityCls, Serializable id) {
28         makeChangeEvent(entityCls, id, EntityChangeEvent.TYPE_ADD);
29     }
30 
31     public void makeUpdateEvent(Class entityCls, Serializable id) {
32         makeChangeEvent(entityCls, id, EntityChangeEvent.TYPE_UPDATE);
33     }
34 
35     private void makeChangeEvent(Class entityCls, Serializable id, int changeType) {
36         EntityChangeEvent e = new EntityChangeEvent(entityCls, id, changeType);
37         if (changeEvents.contains(e)) {
38             changeEvents.remove(e);
39         }
40         changeEvents.add(e);
41         this.setChanged();
42         this.notifyObservers(); 
43     }
44 
45     public List<EntityChangeEvent> getChangeEvents() {
46         return changeEvents;
47     }
48 
49     public void setChangeEvents(List<EntityChangeEvent> changeEvents) {
50         this.changeEvents = changeEvents;
51     }
52 }

 测试

 1 package com.sun.Observer;
 2 
 3 import java.util.Observer;
 4 import java.util.UUID;
 5 
 6 
 7 public class ObserverDemo {
 8     private static EntityEventBlock e = EntityEventBlock.instance();
 9     static {
10         Observer o = new TstObServer();
11         e.addObserver(o);
12     }
13     
14     public static void main(String[] args) {
15         
16         Student s1 = new Student();
17         s1.setId(UUID.randomUUID().toString());
18         add(s1);
19         Student s2 = new Student();
20         s2.setId(UUID.randomUUID().toString());
21         add(s2);
22 
23     }
24 
25     static void update(Entity entity) {
26         e.makeUpdateEvent(entity.getClass(), entity.getId());
27 
28     }
29 
30     static void add(Entity entity) {
31         e.makeAddEvent(entity.getClass(), entity.getId());
32     }
33 
34     static void delete(Entity entity) {
35         e.makeDelEvent(entity.getClass(), entity.getId());
36     }
37 }

 

posted @ 2016-07-27 20:04  user_孙  阅读(185)  评论(0编辑  收藏  举报