徒手擼設計模式-觀察者模式

2022-06-19 15:02:15

概念

當物件間存在一對多關係時,則使用觀察者模式(Observer Pattern)。比如,當一個物件被修改時,則會自動通知依賴它的物件。觀察者模式屬於行為型模式。

參考連線: https://www.runoob.com/design-pattern/observer-pattern.html

程式碼案例

新增觀察者抽象類,引入通知類變數

/**
 * 觀察者抽象類
 */
public abstract class Observer {
    protected Notification notification;
    public abstract String update();
}

 

新增通知類,引入觀察者集合,監聽狀態變更,變更時通知各個觀察者子類

/**
 * 觀察者通知類
 */
@Data
@Slf4j
public class Notification {
    private List<Observer> observers= new ArrayList<Observer>();
    private int state;
    private String type;

    public int getState() {
        return state;
    }
    /**
     * 設定變更狀態並通知各個觀察者子類
     * @param state
     */
    public List<String> setState(int state) {
        this.state = state;
        return notifyAllObservers();
    }

    public String getType() {
        return type;
    }
    /**
     *設定變更型別
     * @return
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * 繫結觀察者-將具體實現類放到觀察者管控範圍內
     * @param observer
     */
    public void attach(Observer observer){
        observers.add(observer);
    }

    /**
     * 更新時通知各個觀察者
     */
    public List<String> notifyAllObservers(){
        List<String> list = new ArrayList<>();
        for (Observer observer : observers) {
            list.add( observer.update());
        }
        return list;
    }
}

 

新增列舉值轉換工具類

@Slf4j
public class TranslateUtil {
    public static String translateEnum(Notification notification, String buPaint) {
        int state = notification.getState();
        String type = notification.getType();
        if (StuEnum.PRODUCT.getKey().equals(type)) {
            type=StuEnum.PRODUCT.getValue();
        }else if (StuEnum.SELL.getKey().equals(type)) {
            type=StuEnum.SELL.getValue();
        }else if (StuEnum.PAINT.getKey().equals(type)) {
            type=StuEnum.PAINT.getValue();
        }
        String stateStr="";
        if (Integer.parseInt(StuEnum.START.getKey())==state) {
            stateStr=StuEnum.START.getValue();
        }else if (Integer.parseInt(StuEnum.STOP.getKey())==state) {
            stateStr=StuEnum.STOP.getValue();
        }else if (Integer.parseInt(StuEnum.WAIT.getKey())==state) {
            stateStr=StuEnum.WAIT.getValue();
        }
        String retStr = type + "===============" + stateStr+"==============="+buPaint+"收到";
        log.info(retStr);
        return retStr;
    }
}

 

完成三個觀察者子類實現

PaintingObserver--噴漆子類

/**
 * 噴漆觀察者子類
 */
@Slf4j
public class PaintingObserver extends Observer {
    /**
     * 將當前子類繫結到通知類中
     * @param notification
     */
    public PaintingObserver(Notification notification) {
        this.notification=notification;
        notification.attach(this);
    }

    @Override
    public String update() {
        log.info("------------------處理噴漆邏輯-------------------");
        return TranslateUtil.translateEnum(notification,StFlag.BU_PAINT);
    }
}

 

ProductObserver--生產子類

/**
 * 生產觀察者子類
 */
@Slf4j
public class ProductObserver extends Observer {
    /**
     * 將當前子類繫結到通知類中
     * @param notification
     */
    public ProductObserver(Notification notification) {
        this.notification=notification;
        notification.attach(this);
    }

    @Override
    public String update() {
        log.info("------------------處理生產邏輯-------------------");
        return TranslateUtil.translateEnum(notification, StFlag.BU_PRODUCT);
    }
}

 

SellObserver--銷售子類

/**
 * 銷售觀察者子類
 */
@Slf4j
public class SellObserver extends Observer {
    /**
     * 將當前子類繫結到通知類中
     * @param notification
     */
    public SellObserver(Notification notification) {
        this.notification=notification;
        notification.attach(this);
    }

    @Override
    public String update() {
        log.info("------------------處理銷售邏輯-------------------");
        return TranslateUtil.translateEnum(notification, StFlag.BU_SELL);
    }
}

 

公共類

public final class StFlag {
    public StFlag() {
    }
    /**
     * 生產部門
     */
    public static final String BU_PRODUCT="生產部門";
    /**
     * 銷售部門
     */
    public static final String BU_SELL="銷售部門";
    /**
     * 噴漆部門
     */
    public static final String BU_PAINT="噴漆部門";
}

 

/**
 * 列舉類
 */
public enum StuEnum {
    PRODUCT("PRODUCT","生產工序"),
    SELL("SELL","銷售工序"),
    PAINT("PAINT","噴漆工序"),
    START("1","開始"),
    STOP("2","停止"),
    WAIT("3","等一等");

    private final String key;
    private final String value;
    StuEnum(String key, String value) {
        this.key=key;
        this.value=value;
    }

    /**
     * 獲取key
     * @return
     */
    public String getKey(){
        return key;
    }

    /**
     * 獲取value
     * @return
     */
    public String getValue(){
        return value;
    }

}

 

測試主類

/**
 * 設計模式控制器
 */
@RestController
@RequestMapping("/designPattern")
@Slf4j
public class DesignController {
    @GetMapping("/observer")
    public ResponseModel observer(int state,String type) {
        Notification notification= new Notification();
        new ProductObserver(notification);
        new PaintingObserver(notification);
        new SellObserver(notification);
        notification.setType(type);
        return new ResponseModel("建造者模式完成", 200, notification.setState(state));
    }
}

 

測試案例

 

 

type:PRODUCT-生產工序,SELL-銷售工序,PAINT-噴漆工序
state:1-開始,2-停止,3-等一等

state=3&type=PRODUCT
2022-06-19 11:40:24.123 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-9】【ProductObserver:252022-06-19 11:40:24.124 INFO  生產工序===============等一等===============生產部門收到 【http-nio-8081-exec-9】【TranslateUtil:272022-06-19 11:40:24.124 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-9】【PaintingObserver:252022-06-19 11:40:24.124 INFO  生產工序===============等一等===============噴漆部門收到 【http-nio-8081-exec-9】【TranslateUtil:272022-06-19 11:40:24.125 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-9】【SellObserver:252022-06-19 11:40:24.125 INFO  生產工序===============等一等===============銷售部門收到 【http-nio-8081-exec-9】【TranslateUtil:27】

state=1&type=PRODUCT
2022-06-19 11:40:29.811 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-10】【ProductObserver:252022-06-19 11:40:29.812 INFO  生產工序===============開始===============生產部門收到 【http-nio-8081-exec-10】【TranslateUtil:272022-06-19 11:40:29.812 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-10】【PaintingObserver:252022-06-19 11:40:29.812 INFO  生產工序===============開始===============噴漆部門收到 【http-nio-8081-exec-10】【TranslateUtil:272022-06-19 11:40:29.812 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-10】【SellObserver:252022-06-19 11:40:29.813 INFO  生產工序===============開始===============銷售部門收到 【http-nio-8081-exec-10】【TranslateUtil:27】

state=2&type=PRODUCT
2022-06-19 11:40:34.842 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-1】【ProductObserver:252022-06-19 11:40:34.842 INFO  生產工序===============停止===============生產部門收到 【http-nio-8081-exec-1】【TranslateUtil:272022-06-19 11:40:34.842 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-1】【PaintingObserver:252022-06-19 11:40:34.842 INFO  生產工序===============停止===============噴漆部門收到 【http-nio-8081-exec-1】【TranslateUtil:272022-06-19 11:40:34.843 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-1】【SellObserver:252022-06-19 11:40:34.843 INFO  生產工序===============停止===============銷售部門收到 【http-nio-8081-exec-1】【TranslateUtil:27】

state=3&type=PAINT
2022-06-19 11:40:41.011 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-2】【ProductObserver:252022-06-19 11:40:41.012 INFO  噴漆工序===============等一等===============生產部門收到 【http-nio-8081-exec-2】【TranslateUtil:272022-06-19 11:40:41.014 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-2】【PaintingObserver:252022-06-19 11:40:41.015 INFO  噴漆工序===============等一等===============噴漆部門收到 【http-nio-8081-exec-2】【TranslateUtil:272022-06-19 11:40:41.015 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-2】【SellObserver:252022-06-19 11:40:41.015 INFO  噴漆工序===============等一等===============銷售部門收到 【http-nio-8081-exec-2】【TranslateUtil:27】

state=2&type=PAINT
2022-06-19 11:40:47.334 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-3】【ProductObserver:252022-06-19 11:40:47.334 INFO  噴漆工序===============停止===============生產部門收到 【http-nio-8081-exec-3】【TranslateUtil:272022-06-19 11:40:47.335 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-3】【PaintingObserver:252022-06-19 11:40:47.335 INFO  噴漆工序===============停止===============噴漆部門收到 【http-nio-8081-exec-3】【TranslateUtil:272022-06-19 11:40:47.335 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-3】【SellObserver:252022-06-19 11:40:47.335 INFO  噴漆工序===============停止===============銷售部門收到 【http-nio-8081-exec-3】【TranslateUtil:27】

state=1&type=PAINT
2022-06-19 11:40:54.004 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-4】【ProductObserver:252022-06-19 11:40:54.006 INFO  噴漆工序===============開始===============生產部門收到 【http-nio-8081-exec-4】【TranslateUtil:272022-06-19 11:40:54.006 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-4】【PaintingObserver:252022-06-19 11:40:54.007 INFO  噴漆工序===============開始===============噴漆部門收到 【http-nio-8081-exec-4】【TranslateUtil:272022-06-19 11:40:54.007 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-4】【SellObserver:252022-06-19 11:40:54.007 INFO  噴漆工序===============開始===============銷售部門收到 【http-nio-8081-exec-4】【TranslateUtil:27】

state=3&type=SELL
2022-06-19 11:40:57.847 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-5】【ProductObserver:252022-06-19 11:40:57.847 INFO  銷售工序===============等一等===============生產部門收到 【http-nio-8081-exec-5】【TranslateUtil:272022-06-19 11:40:57.847 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-5】【PaintingObserver:252022-06-19 11:40:57.847 INFO  銷售工序===============等一等===============噴漆部門收到 【http-nio-8081-exec-5】【TranslateUtil:272022-06-19 11:40:57.850 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-5】【SellObserver:252022-06-19 11:40:57.850 INFO  銷售工序===============等一等===============銷售部門收到 【http-nio-8081-exec-5】【TranslateUtil:27】

state=2&type=SELL
2022-06-19 11:41:02.659 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-6】【ProductObserver:252022-06-19 11:41:02.659 INFO  銷售工序===============停止===============生產部門收到 【http-nio-8081-exec-6】【TranslateUtil:272022-06-19 11:41:02.660 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-6】【PaintingObserver:252022-06-19 11:41:02.662 INFO  銷售工序===============停止===============噴漆部門收到 【http-nio-8081-exec-6】【TranslateUtil:272022-06-19 11:41:02.663 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-6】【SellObserver:252022-06-19 11:41:02.663 INFO  銷售工序===============停止===============銷售部門收到 【http-nio-8081-exec-6】【TranslateUtil:27】

state=1&type=SELL
2022-06-19 11:41:08.188 INFO  ------------------處理生產邏輯------------------- 【http-nio-8081-exec-7】【ProductObserver:252022-06-19 11:41:08.188 INFO  銷售工序===============開始===============生產部門收到 【http-nio-8081-exec-7】【TranslateUtil:272022-06-19 11:41:08.189 INFO  ------------------處理噴漆邏輯------------------- 【http-nio-8081-exec-7】【PaintingObserver:252022-06-19 11:41:08.190 INFO  銷售工序===============開始===============噴漆部門收到 【http-nio-8081-exec-7】【TranslateUtil:272022-06-19 11:41:08.192 INFO  ------------------處理銷售邏輯------------------- 【http-nio-8081-exec-7】【SellObserver:252022-06-19 11:41:08.192 INFO  銷售工序===============開始===============銷售部門收到 【http-nio-8081-exec-7】【TranslateUtil:27】