18 行为型模式-观察者模式

行为模式共有11种:

观察者模式
模板方法模式
策略模式
职责链模式
状态模式
命令模式
中介者模式
迭代器模式
访问者模式
备忘录模式
解释器模式

以上 11 种行为型模式,除了模板方法模式解释器模式是类行为型模式,其他的全部属于对象行为型模式。

1 观察者模式介绍


2 观察者模式原理


3 观察者模式实现
java 复制代码
/**
 * 抽象观察者
 **/
public interface Observer {
    //update方法: 为不同的观察者更新行为定义一个相同的接口,不同的观察者对该接口有不同的实现
    public void update();
}
java 复制代码
/**
 * 具体的观察者
 **/
public class ConcreteObserver1 implements Observer {

    @Override
    public void update() {
        System.out.println("ConcreteObserver1 得到通知,更新状态! !");
    }
}
java 复制代码
public class ConcreteObserver2  implements Observer{
    @Override
    public void update() {
        System.out.println("ConcreteObserver2 得到通知,更新状态! !");
    }
}
java 复制代码
/**
 * 抽象目标类
 **/
public interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers();
}
java 复制代码
import java.util.ArrayList;

/**
 * 具体目标类
 **/
public class ConcreteSubject implements Subject {

    //定义集合,存储所有的观察者对象
    private ArrayList<Observer> observers = new ArrayList<>();


    //注册方法,向观察者集合增加一个观察者
    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }

    //注销方法,用于从观察者集合中移除一个观察者
    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    //通知方法
    @Override
    public void notifyObservers() {
        //遍历集合,调用每一个观察者的响应方法
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
java 复制代码
public class Client {

    public static void main(String[] args) {

        //创建目标类
        Subject subject = new ConcreteSubject();

        //注册观察者,注册多个
        subject.attach(new ConcreteObserver1());
        subject.attach(new ConcreteObserver2());

        //具体的主题内部发生改变,给所有注册的观察者发送通知
        subject.notifyObservers();
    }
}
4 观察者模式应用实例

来实现一个买房摇号的程序.摇号结束,需要通过短信告知用户摇号结果,还需要向MQ中保存用户本次摇号的信息.

1 ) 未使用设计模式
java 复制代码
/**
 * 模拟买房摇号服务
 **/
public class DrawHouseService {

    //摇号抽签
    public String lots(String uId){
        if(uId.hashCode() % 2 == 0){
            return "恭喜ID为: " + uId + " 的用户,在本次摇号中中签!" ;
        }else{
            return "很遗憾,ID为: " + uId + "的用户,您本次未中签!" ;
        }
    }
}
java 复制代码
/**
 * 开奖结果封装类
 **/
public class LotteryResult {

    private String uId; //用户id

    private String msg; //摇号信息

    private Date dateTime; //业务时间

    public LotteryResult(String uId, String msg, Date dateTime) {
        this.uId = uId;
        this.msg = msg;
        this.dateTime = dateTime;
    }

    @Override
    public String toString() {
        return "LotteryResult{" +
                "uId='" + uId + '\'' +
                ", msg='" + msg + '\'' +
                ", dateTime=" + dateTime +
                '}';
    }

    public String getuId() {
        return uId;
    }

    public void setuId(String uId) {
        this.uId = uId;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Date getDateTime() {
        return dateTime;
    }

    public void setDateTime(Date dateTime) {
        this.dateTime = dateTime;
    }
}
java 复制代码
/**
 * 开奖服务接口
 **/
public interface LotteryService {
    //开奖之后的业务操作
    public LotteryResult lottery(String uId);

}
java 复制代码
public class LotteryServiceImpl implements LotteryService {

    //注入摇号服务
    private DrawHouseService houseService = new DrawHouseService();

    @Override
    public LotteryResult lottery(String uId) {
        //1.摇号
        String result = houseService.lots(uId);

        //2.发短信
        System.out.println("发送短信通知用户,ID为: " + uId +",您的摇号结果如下: " + result);

        //3.发送MQ信息
        System.out.println("记录用户摇号结果到MQ,ID为: " + uId +",摇号结果: " + result);

        return new LotteryResult(uId,result,new Date());
    }
}
使用观察者模式进行优化
java 复制代码
/**
 * 事件监听接口
 **/
public interface EventListener {
	//充当观察者的角色,对结果进行监听
    void doEvent(LotteryResult result);
}
java 复制代码
/**
 * 短信发送事件监听类
 **/
public class MessageEventListener implements EventListener {
    @Override
    public void doEvent(LotteryResult result) {
        System.out.println("发送短信通知,用户ID: " + result.getuId()
        +",您的摇号结果为: " + result.getMsg());
    }
}
java 复制代码
/**
 * MQ消息发送事件监听
 **/
public class MQEventListener implements EventListener{

    @Override
    public void doEvent(LotteryResult result) {
        System.out.println("记录用户的摇号结果(MQ),用户ID: " + result.getuId()
        + ",摇号结果: " + result.getMsg());
    }
}
java 复制代码
/**
 * 事件处理类
 **/
public class EventManager {

    public enum EventType{
        MQ,Message
    }

    //监听器集合
    Map<Enum<EventType>, List<EventListener>> listeners = new HashMap<>();

    public EventManager(Enum<EventType>... operations) {
        for (Enum<EventType> operation : operations) {
            this.listeners.put(operation,new ArrayList<>());
        }
    }

    /**
     * 订阅
     * @param eventType 事件类型
     * @param listener  监听对象
     */
    public void subscribe(Enum<EventType> eventType,EventListener listener){
        List<EventListener> users = listeners.get(eventType);
        users.add(listener);
    }

    /**
     * 取消订阅
     * @param eventType 事件类型
     * @param listener  监听对象
     */
    public void unsubscribe(Enum<EventType> eventType,EventListener listener){
        List<EventListener> users = listeners.get(eventType);
        users.remove(listener);
    }

    /**
     * 通知
     * @param eventType
     * @param result
     */
    public void notify(Enum<EventType> eventType, LotteryResult result){
        List<EventListener> users = listeners.get(eventType);
        for (EventListener listener : users) {
            listener.doEvent(result);
        }
    }
}
java 复制代码
/**
 * 开奖服务接口
 **/
public abstract class LotteryService {

    private EventManager eventManager;

    public LotteryService() {
        //设置事件的类型
        eventManager = new EventManager(EventManager.EventType.MQ,EventManager.EventType.Message);
        //订阅
        eventManager.subscribe(EventManager.EventType.Message,new MessageEventListener());
        eventManager.subscribe(EventManager.EventType.MQ,new MQEventListener());
    }

    public LotteryResult lotteryAndMsg(String uId){
        LotteryResult lottery = lottery(uId);
        //发送通知
        eventManager.notify(EventManager.EventType.Message,lottery);
        eventManager.notify(EventManager.EventType.MQ,lottery);

        return lottery;
    }

    public abstract LotteryResult lottery(String uId);
}
java 复制代码
public class LotteryServiceImpl extends LotteryService {

    //注入摇号服务
    private DrawHouseService houseService = new DrawHouseService();

    @Override
    public LotteryResult lottery(String uId) {
        //1.摇号
        String result = houseService.lots(uId);
        return new LotteryResult(uId,result,new Date());
    }
}

测试

java 复制代码
@Test
public void test2(){
	LotteryService ls = new LotteryServiceImpl();
	LotteryResult result = ls.lotteryAndMsg("1234567887654322");
	System.out.println(result);
}
5 观察者模式总结



相关推荐
东风吹柳2 天前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
T1an-12 天前
设计模式之【观察者模式】
观察者模式·设计模式
真想骂*5 天前
观察者模式:它究竟在观察什么?
java·开发语言·观察者模式
夏旭泽6 天前
设计模式-观察者模式
观察者模式·设计模式
澄澈i7 天前
设计模式学习[12]---观察者模式
学习·观察者模式·设计模式
问道飞鱼9 天前
【设计模式】观察者模式深度讲解
观察者模式·设计模式
吾与谁归in10 天前
【C#设计模式(20)——观察者模式(Observer Pattern)】
观察者模式·设计模式·c#
你又食言了哦17 天前
C++观察者模式Observer
开发语言·c++·观察者模式
ohMyGod_12317 天前
手写观察者模式
观察者模式
Theodore_102219 天前
14 设计模式值观察者模式(书籍发布通知案例)
java·开发语言·算法·观察者模式·设计模式·java-ee