設計模式-模板方法模式

如約而至,開始模板方法模式學習的旅途……
 
 
一、模板方法模式定義
模板方法模式定義一個操作中的算法骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變算法結構即可重新定義該算法的某些特定步驟。
 
二、模板方法模式使用場景 
1、使用場景
(1)、當子類中有一些不變的通用的算法時,可以把這些提升到父類,減少代碼重複,特定子類相關步驟在子類中完成。
 
2、類圖
模板方法模式URL包括兩個角色:抽象模板類和實現類
AbstractClass 模板方法類模板模板方法定義類算法骨架,operation 運算方法被延遲到子類中實現。
ConcreteClass 實現抽象方法、重寫父類方法完成算法中與特定子類相關的步驟。
模板方法類中去了定義模板方法,抽象方法外還可以定義通用方法(減少代碼重複)、鉤子方法(子類擴展)來服務子類。
 
三、代碼展示
 
1、模板方法類
public abstract class AbstractClass {

    /**
     * 模板方法定義算法流程
     */
    public void template() {
        //起牀
        operation1();
        //洗漱
        operation2();
        //跑步
        operation3();
        //早飯
        operation4();
        //上班
        operation5();
    }

    /**
     * 算法中所有子類公工操作
     */
    public void operation1() {
        System.out.println("起牀");
    }

    /**
     * 算法中所有子類公工操作
     */
    public void operation2() {
        System.out.println("洗漱");
    }

    /**
     * 算法中默認操作
     */
    public void operation3() {
        System.out.println("室內跑步");
    }

    /**
     * 算法中子類特定操作
     */
    public abstract void operation4();

    /**
     * 算法中子類公共操作
     */
    public void operation5() {
        System.out.println("上班");
    }
}

2、實現類

(1)、實現抽象類
public class ConcreteClass extends AbstractClass {

    @Override
    public void operation4() {
        System.out.println("早飯喝粥");
    }
}

(2)、實現抽象類,重寫父類方法

public class ConcreteClass2 extends AbstractClass {


    @Override
    public void operation3() {
        System.out.println("室外跑步");
    }

    @Override
    public void operation4() {
        System.out.println("早飯吃麪");
    }
}

在看看項目中使用到的模板方法模式

多個MQ消費者創建消費消息:
(1)、獲取MQ配置屬性(group、nameServer、topic、tag……)
(2)、創建消費者設置消費者屬性
(3)、註冊監聽類
(4)、遍歷消息對象
(5)、處理消息
在這樣的一個流程中,獲取MQ配置屬性和各個對象處理消息是需要按照自己需求進行處理,其他的流程都是一樣的,所以我們可以使用模板方法模式來實現這樣的一個流程。
 
1、模板方法類
public abstract class AbstractConsumer {
    /**
     * 配置文件
     */
    private Map<String, String> properties = Maps.newHashMap();

    /**
     * 消費對象
     */
    DefaultMQPushConsumer consumer = null;

    /**
     * 配置屬性按照子類配置獲取
     *
     * @return
     */
    abstract Map<String, String> getProperties();

    /**
     * 具體子類消息處理方法
     *
     * @param key
     * @param messageBody
     * @return
     */
    abstract Boolean handler(String key, String messageBody);


    /**
     * 這裏相當於是模板方法
     */
    public void listener() {
        try {
            // 配置屬性獲取
            properties = getProperties();
            // 對象
            consumer = new DefaultMQPushConsumer(properties.get("group"));
            // 屬性設置……
            consumer.setNamesrvAddr(properties.get("nameServer"));
            // 註冊監聽
            consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {

                for (int i = 0; i < msgs.size(); i++) {
                    MessageExt msgExt = msgs.get(i);
                    String key = msgExt.getMsgId();
                    String msgBody = new String(msgExt.getBody());
                    // 消息處理
                    handler(key, msgBody);
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            });
            consumer.start();
        } catch (MQClientException e) {
            logger.error("mqProperty:{}", JSON.toJSONString(mqProperty), e);
        }

    }
}

2、實現類

(1)、B端數據消費
public class Customer2B extends AbstractConsumer {
    @Override
    protected Map<String, String> getProperties() {
        Map<String, String> param = Maps.newHashMap();
        param.put("group", "ToB");
        param.put("nameServer", "127.0.0.1:8090");
        return param;
    }

    @Override
    Boolean handler(String key, String messageBody) {
        //數據入庫B
        return true;
    }
}

(2)、C端數據消費

public class Customer2C extends AbstractConsumer {
    @Override
    protected Map<String, String> getProperties() {
        Map<String, String> properties = Maps.newHashMap();
        properties.put("group", "ToC");
        properties.put("nameServer", "127.0.0.1:8090");
        return properties;
    }

    @Override
    Boolean handler(String key, String messageBody) {
        //數據入庫C
        return true;
    }
}

四、優點

1、它把不變部分的算法封裝到父類中實現,而把可變部分算法由子類繼承實現,便於子類繼續擴展。
2、它在父類中提取了公共的部分代碼,便於代碼複用。
3、部分方法是由子類實現的,因此子類可以通過擴展方式增加相應的功能,符合開閉原則。
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章