天天看點

java訂閱釋出案例,結合觀察者模式

應用場景:

     用java寫一個服務端程式,可以接受訂閱和取消訂閱,或拉取,和主動推送。初步一想,似乎很簡單,但做成容易擴充和類似架構結構,就沒那麼随意設計了。當然,本人也是個新手,閱讀了設計模式一書中的觀察者模式,不斷寫一些小demo,為了充分了解面向接口面層,也是從定義頂層接口入手了。

功能說明:

  貼測試類代碼了。注釋很明白了。

public static void main(String[] args) {
    //init register
    //1.currentTObserver,displyTObserver兩個觀察者(用戶端)。
    CurrentTObserver currentTObserver=new CurrentTObserver("CurObserver1");
    DisplyTObserver displyTObserver=new DisplyTObserver("DisObserver");

    //2.兩個觀察者(用戶端)訂閱了不同類型,品種的資料。currentTObserver訂閱了兩種個容器的資料,另外一個隻訂閱了天氣容器中的資料。
    WeatherSubjectContainer.getInstance().registerObserver(currentTObserver);
    WeatherSubjectContainer.getInstance().registerObserver(displyTObserver);
    CarSubjectContainer.getInstance().registerObserver(currentTObserver);

    //3.WeatherSubjectContainer和CarSubjectContainer兩種資料發生了改變的時候,調用自己的dateChange方法,兩個用戶端就可以收到對應資料了。
    //4.擴充資料品種增加一個container,增加一種資料類型即可。
    int te = 1;
    int hum = 3;
    while (true) {
        try {
            Thread.sleep(1000);
            System.out.println(" data rescore push data ...");
            te++;
            hum++;
            WeaterDate weaterDate = new WeaterDate("WD_DATA");
            weaterDate.setTemperature(te);
            weaterDate.setHumidity(hum);
            WeatherSubjectContainer.getInstance().dateChange(weaterDate);

            CarDate carDate = new CarDate("CAR_DATA");
            carDate.setCarNum("CarA0000");
            carDate.setCarStatus("空");
            CarSubjectContainer.getInstance().dateChange(carDate);
            //模拟取消訂閱
            if (te>5){
                WeatherSubjectContainer.getInstance().rmoveObserver(currentTObserver);
            }
            System.out.println("WE->"+WeatherSubjectContainer.getInstance().getMapSize());
            System.out.println("Cr->"+CarSubjectContainer.getInstance().getMapSize());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}      

1.項目結構:

java訂閱釋出案例,結合觀察者模式

2.結構說明:

core包中包括兩個頂層接口,一個主題抽象類,資料的抽象類,基類,觀察者的基類。所有的相關的新寫的對象都要繼承或實作其中的特有方法。model包中定義資料具體類,繼承BaseDate,observer包中是所有觀察者,自己定義,需要繼承BaseTobserver類。subject包中就是資料容器了。資料添加進容器不在這裡讨論了。

3.核心如下代碼:其中沒使用到的方法和接口中的内容是為了擴充應用。實際是用不到可以削減方法。後面的subject和model,就看實際業務資料怎麼樣就怎麼寫了。做好繼承就行。觀察者的話,接收到資料分類處理即可。

public abstract class BaseDate {
    private String dataId;

    public BaseDate(String dataId) {
        this.dataId = dataId;
    }

    public String getDataId() {
        return dataId;
    }

    public void setDataId(String dataId) {
        this.dataId = dataId;
    }
}      
public abstract class BaseToserver implements TObserver {
    private String observerId;


    public BaseToserver(String observerId) {
        this.observerId = observerId;
    }

    public abstract void update(BaseDate baseDate);

    public abstract void init(BaseDate baseDate);

    public String getObserverId() {
        return observerId;
    }

    public void setObserverId(String observerId) {
        this.observerId = observerId;
    }
}      
public abstract class Subject implements TObservable {
    public static Logger LOG = LoggerFactory.getLogger(Subject.class);

    private BaseDate data;
    private ConcurrentHashMap<String, BaseToserver> submap = new ConcurrentHashMap<>();

    @Override
    public void registerObserver(BaseToserver o) {

        submap.put(o.getObserverId(), o);

    }

    @Override
    public void rmoveObserver(BaseToserver o) {
        if (submap.containsKey(o.getObserverId())) {
            submap.remove(o.getObserverId());
        } else {
            LOG.error(" remove failed " + o.getObserverId());
        }

    }

    @Override
    public void notifyObsevers() {
        Set<Map.Entry<String, BaseToserver>> entrySet = submap.entrySet();
        for (Map.Entry<String, BaseToserver> entry : entrySet
                ) {
            entry.getValue().update(data);
        }
    }

    @Override
    public void dateChange(BaseDate o) {
        this.data = o;
        notifyObsevers();
    }

    public int getMapSize() {
        return submap.size();
    }
}      
public interface TObservable {
    public void registerObserver(BaseToserver o);

    public void rmoveObserver(BaseToserver o);

    public void notifyObsevers();

    public void dateChange(BaseDate o);
}
      
public interface TObserver<T> {
    public void TestHandle();
}      
public class CarDate extends BaseDate{
    public CarDate(String dateId) {
        super(dateId);
    }
    private String carNum;
    private String carStatus;

    public String getCarNum() {
        return carNum;
    }

    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    public String getCarStatus() {
        return carStatus;
    }

    public void setCarStatus(String carStatus) {
        this.carStatus = carStatus;
    }
}      
public class CurrentTObserver extends BaseToserver {


    public CurrentTObserver(String observerId) {
        super(observerId);
    }

    @Override
    public void update(BaseDate baseDate) {

        if (baseDate instanceof WeaterDate) {
            WeaterDate date = (WeaterDate) baseDate;
            System.out.println(" Current observer receive WeaterDate-> " + date.getHumidity() + "-" + date.getTemperature());
        } else if (baseDate instanceof CarDate) {
            CarDate carDate = (CarDate) baseDate;
            System.out.println(" Current observer receive carDate> " + carDate.getCarNum() + "-" + carDate.getCarStatus());
        }

    }

    @Override
    public void init(BaseDate BaseDate) {

    }

    @Override
    public void TestHandle() {

    }
}      
public class CarSubjectContainer extends Subject{
    private static WeatherSubjectContainer ourInstance = new WeatherSubjectContainer();

    public static WeatherSubjectContainer getInstance() {
        return ourInstance;
    }
}      

4.總結:根據設計模式和合理使用抽象類的程式設計設計,還是第一次從這種角度去考慮。感覺很不錯。模型有了,解讀源碼和架構就更舒服了。觀察者和資料類型完整代碼資料下載下傳位址:https://download.csdn.net/download/flybridy/10460374

繼續閱讀