1. 程式人生 > >Java設計模式 - 觀察者模式

Java設計模式 - 觀察者模式

觀察者模式

觀察者模式也可以被稱為註冊/訂閱模式.當一個物件的狀態發生變化的時候,所有依賴於它的其他類會受到通知並自動更新.

UML圖示

觀察者模式的UML圖示

觀察者模式所含有的角色

  1. 主題(Subject):介面,一定會擁有新增觀察者方法的定義以及通知觀察者的方法定義
  2. 具體主題(SubjectImpl):類,實現主題的一個例項。
  3. 觀察者(Observer):介面,擁有接受主題傳送訊息的方法定義。
  4. 具體觀察者(ObserverImpl):類,擁有主題物件的引用接受訊息的實現以及呼叫主題物件新增觀察者方法的程式段

舉例

介面(MessageReceiver.java)用於接受外部傳來的各種訊息,存在MessageHandler.java介面用於處理訊息。同時TradeReceiver.java用於接收trade訊息,同時需要在接到訊息後通知StringMessageHandler.java以及MapMessageHandler.java用於處理不同型別的trade訊息。

採用觀察者模式對系統完成設計

類結構

- MessageHandler

package Handler;

public interface MessageHandler {

    public void handleMessage();
}

-MapObjectMessagerHandler.java

MessageHandler的實現類,擁有處理訊息的具體實現以及將本類的例項加入subject的名單中(註冊)。

package Handler.Impl;

import Handler.MessageHandler;
import Recevier.MessageReceiver;

/**
 * Created by YL28537 on 10/09/2018.
 */
public class MapObjectMessageHandler implements MessageHandler {

    private MessageReceiver messageReceiver;

    public MapObjectMessageHandler(MessageReceiver messageReceiver){
        this.messageReceiver = messageReceiver;
        messageReceiver.addHandler(this);
    }

    @Override
    public void handleMessage(){
        System.out.println("Handling by MapObjectMessageHandler");
    }
}

- StringMessageHandler.java

package Handler.Impl;

import Handler.MessageHandler;
import Recevier.MessageReceiver;

/**
 * Created by YL28537 on 10/09/2018.
 */
public class StringMessageHandler implements MessageHandler{

    private MessageReceiver messageReceiver;

    public StringMessageHandler(MessageReceiver messageReceiver){
        this.messageReceiver = messageReceiver;
        messageReceiver.addHandler(this);
    }
    @Override
    public void handleMessage(){
        System.out.println("Handling by StringMessageHandler");
    }
}

- Recevier.java

package Recevier;

import Handler.MessageHandler;

/**
 * Created by YL28537 on 10/09/2018.
 */
public interface MessageReceiver {

    public void addHandler(MessageHandler messageHandler);

    public void deleteHandler();

    public void notifyAllHandler();
}

- TradeRecevier.java

package Recevier.Impl;

import Handler.MessageHandler;
import Recevier.MessageReceiver;

import java.util.ArrayList;

/**
 * Created by YL28537 on 10/09/2018.
 */
public class TradeReceiver implements MessageReceiver {

    private ArrayList<MessageHandler> handlers= new ArrayList<>();

    @Override
    public void addHandler(MessageHandler messageHandler) {
        handlers.add(messageHandler);
    }

    @Override
    public void deleteHandler() {
        if(handlers.size()!=0){
            for(int i = 0 ; i <= handlers.size() ; i++){
                handlers.remove(1);
            }
        }else{
            return;
        }
    }

    @Override
    public void notifyAllHandler() {
        if(handlers.size()!=0){
            for(MessageHandler handler : handlers){
                 handler.handleMessage();
            }
        }else{
            System.out.println("No avaliable Handlers!");
            return;
        }
    }
}

- Application.java

import Handler.Impl.MapObjectMessageHandler;
import Handler.Impl.StringMessageHandler;
import Recevier.Impl.TradeReceiver;
import Recevier.MessageReceiver;

/**
 * Created by YL28537 on 10/09/2018.
 */
public class Application {

    public static void main(String[] args){
        MessageReceiver receiver = new TradeReceiver();

        //setup a MapObjectMessageHandler
        MapObjectMessageHandler mapObjectMessageHandler= new MapObjectMessageHandler(receiver);
        //setup a StringMessageHandler
        StringMessageHandler stringMessageHandler = new StringMessageHandler(receiver);
        //handle Message
        receiver.notifyAllHandler();
    }

}

 

模擬使用Spring來管理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <bean id="subject" class="Recevier.MessageReceiver" />

    <bean id="subjectImpl" parent="subject" class="Recevier.Impl.TradeReceiver"/>

    <bean id="observer" class="Handler.MessageHandler"/>

    <bean id="objectImpl1" parent="observer" class="Handler.Impl.StringMessageHandler">
        <property name="messageReceiver" ref="subject"/>
        <constructor-arg>
            <ref-bean="subject"/>
        </constructor-arg>
    </bean>

</beans>


推資料與拉資料

推資料:直接告訴observer實際的訊息內容。

拉資料:將變化後的訊息存到某個物件中,然後告訴observer變化的訊息,observer根據自身需求決定取回的訊息內容。

 

觀察者模式與多主題

一個觀察者可以訂閱多個主題,要求某一主題發生變化後,通知本類。

實現:只需要在observer中新增邏輯,決定接受哪一主題。