1. 程式人生 > >設計模式之觀察者模式(Observe)-泛型擴充套件

設計模式之觀察者模式(Observe)-泛型擴充套件

設計模式之觀察者模式(Observer)

擴充套件部分是很精彩

意圖

定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。

場景

觀測天氣(機器觀測,人工觀測),天氣變化時,觀測者做相應的處理

天氣觀測示例

天氣型別

public enum WeatherType {

  SUNNY, RAINY, WINDY, COLD;

  @Override
  public String toString() {
    return this.name().toLowerCase();
  }
}

觀測者介面

public interface
WeatherObserver { void update(WeatherType currentWeather); }

天氣類

public class Weather {

    private WeatherType currentWeather;
    private List<WeatherObserve> observes;

    public Weather(){
        currentWeather = WeatherType.SUNNY;
        observes = new ArrayList<>();
    }
public void addObserver(WeatherObserve observe){ observes.add(observe); } public void removeObserver(WeatherObserve observe){ observes.remove(observe); } public void timePassBy(){ WeatherType[] types = WeatherType.values(); currentWeather = types[
(currentWeather.ordinal()+1)%types.length]; System.out.println(MessageFormat.format("The weather change to {0}",currentWeather)); notifyObservers(); } private void notifyObservers(){ for (WeatherObserve observe : observes){ observe.update(currentWeather); } } }

機器觀測類

public class HobbitObserve implements WeatherObserve {
    @Override
    public void update(WeatherType currentWeather) {
        switch (currentWeather) {
            case COLD:
                System.out.println("The hobbits are shivering in the cold weather.");
                break;
            case RAINY:
                System.out.println("The hobbits look for cover from the rain.");
                break;
            case SUNNY:
                System.out.println("The happy hobbits bade in the warm sun.");
                break;
            case WINDY:
                System.out.println("The hobbits hold their hats tightly in the windy weather.");
                break;
            default:
                break;
        }
    }
}

人工觀測

public class OrcsObserve implements WeatherObserve{
    @Override
    public void update(WeatherType currentWeather) {
        switch (currentWeather) {
            case COLD:
                System.out.println("The orcs are shivering in the cold weather.");
                break;
            case RAINY:
                System.out.println("The orcs look for cover from the rain.");
                break;
            case SUNNY:
                System.out.println("The orcs hobbits bade in the warm sun.");
                break;
            case WINDY:
                System.out.println("The orcs hold their hats tightly in the windy weather.");
                break;
            default:
                break;
        }
    }
}

測試

   @Test
    public void observeTest(){
        Weather weather = new Weather();
        weather.addObserver(new HobbitObserve());
        weather.addObserver(new OrcsObserve());

        weather.timePassBy();
        weather.timePassBy();
        weather.timePassBy();
        weather.timePassBy();
        weather.timePassBy();
    }

類圖 在這裡插入圖片描述

觀測者模式擴充套件

使用泛型進行擴充套件

觀察目標需繼承此類 S:觀測類 O:觀察者類 A:觀測引數

public abstract class Observable<S extends Observable<S,O,A>,O extends Observer<S,O,A>,A> {

    protected List<O> observers;

    public Observable(){
        observers = new CopyOnWriteArrayList<>();
    }

    public void addObserver(O observer){
        observers.add(observer);
    }

    public void remove(O observer){
        observers.remove(observer);
    }

    public void notifyObserver(A arguments){
        for (O observer : observers){
            observer.update((S) this,arguments);
        }
    }
}

觀察者介面

public interface Observer<S extends Observable<S,O,A>,O extends Observer<S,O,A>,A> {

    void update(S subject,A argument);
}

天氣觀察者

public interface Race extends Observer<GWeather,Race,WeatherType> {
}

天氣類

public class GWeather extends Observable<GWeather,Race,WeatherType> {

    private WeatherType currentWeather;

    public GWeather(){
        currentWeather = WeatherType.SUNNY;
    }

    public void timePassBy(){
        WeatherType[] enumsValues = WeatherType.values();
        currentWeather = enumsValues[(currentWeather.ordinal()+1)%enumsValues.length];
        System.out.println(MessageFormat.format("The weather change to {0}",currentWeather));
        notifyObserver(currentWeather);
    }


}

機器觀察

public class GHobbitObserver implements Race {
    @Override
    public void update(GWeather subject, WeatherType currentWeather) {
        switch (currentWeather) {
            case COLD:
                System.out.println("The hobbits are shivering in the cold weather.");
                break;
            case RAINY:
                System.out.println("The hobbits look for cover from the rain.");
                break;
            case SUNNY:
                System.out.println("The happy hobbits bade in the warm sun.");
                break;
            case WINDY:
                System.out.println("The hobbits hold their hats tightly in the windy weather.");
                break;
            default:
                break;
        }
    }
}

人工觀察

public class GOrcsObserver implements Race {
    @Override
    public void update(GWeather subject, WeatherType currentWeather) {
        switch (currentWeather) {
            case COLD:
                System.out.println("The orcs are shivering in the cold weather.");
                break;
            case RAINY:
                System.out.println("The orcs look for cover from the rain.");
                break;
            case SUNNY:
                System.out.println("The orcs hobbits bade in the warm sun.");
                break;
            case WINDY:
                System.out.println("The orcs hold their hats tightly in the windy weather.");
                break;
            default:
                break;
        }
    }
}

測試

  @Test
    public void genericTest(){
        GWeather gWeather = new GWeather();
        gWeather.addObserver(new GOrcsObserver());
        gWeather.addObserver(new GHobbitObserver());

        gWeather.timePassBy();
        gWeather.timePassBy();
        gWeather.timePassBy();
        gWeather.timePassBy();
    }

泛型做的是型別限制 類圖 在這裡插入圖片描述