設計模式-行為型模式(一)


一、責任鏈模式

用於避免請求發送者與多個請求處理者耦合在一起,讓所有請求的處理者持有下一個對象的引用,從而將請求串聯成一條鏈,在有請求發生時,可將請求沿着這條鏈傳遞,直到遇到該對象的處理器。

通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那么它會把相同的請求傳給下一個接收者,依此類推。

 

以用戶發送Web請求,經過用戶鑒權、業務調用、結果反饋流程為例:

(1)定義Handler接口:

public interface Handler {
    void operator();
}

(2)定義AbstractHandler類:

public abstract class AbstractHandler {
    private Handler handler;

    public Handler getHandler() {
        return handler;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }
}

(3)定義用戶授權類AuthHandler、業務處理類BusinessHandler、結果反饋類ResponseHandler

public class AuthHandler extends AbstractHandler implements Handler {
    private final static Log logger = LogFactory.getLog(AuthHandler.class);
    private String name;
    public AuthHandler(String name){
        this.name = name;
    }
    @Override
    public void operator() {
        logger.info("user auth");
        if(getHandler()!=null){
            //執行責任鏈下一流程
            getHandler().operator();
        }
    }
}

public class BusinessHandler extends AbstractHandler implements Handler {
    private final static Log logger = LogFactory.getLog(BusinessHandler.class);
    private String name;
    public BusinessHandler(String name){
        this.name = name;
    }
    @Override
    public void operator() {
        logger.info("Business info handler");
        if(getHandler()!=null){
            //執行責任鏈下一流程
            getHandler().operator();
        }
    }
}

public class ResponseHandler extends AbstractHandler implements Handler {
    private final static Log logger = LogFactory.getLog(ResponseHandler.class);
    private String name;
    public ResponseHandler(String name){
        this.name = name;
    }
    @Override
    public void operator() {
        logger.info("message response");
        if(getHandler()!=null){
            //執行責任鏈下一流程
            getHandler().operator();
        }
    }
}

(4)使用責任鏈模型:

public class Main {
    public static void main(String[] args) {
        AuthHandler authHandler = new AuthHandler("auth");
        BusinessHandler businessHandler = new BusinessHandler("business");
        ResponseHandler responseHandler = new ResponseHandler("response");
        authHandler.setHandler(businessHandler);
        businessHandler.setHandler(responseHandler);
        authHandler.operator();
    }
}

結果:

十二月 30, 2019 10:06:15 下午 com.jzq.sign.Responsibility.AuthHandler operator
信息: user auth
十二月 30, 2019 10:06:15 下午 com.jzq.sign.Responsibility.BusinessHandler operator
信息: Business info handler
十二月 30, 2019 10:06:15 下午 com.jzq.sign.Responsibility.ResponseHandler operator
信息: message response

二、命令模式

請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。

 

 (1)創建一個Command接口:

public interface Command {
    void execute();
}

(2)創建請求類Stock:

public class Stock {

    private String name = "ABC";
    private int quantity = 10;

    public void buy(){
        System.out.println("Stock [ Name: "+name+",Quantity: " + quantity +" ] bought");
    }
    public void sell(){
        System.out.println("Stock [ Name: "+name+",Quantity: " + quantity +" ] sold");
    }
}

(3)創建實現了Command 接口的實體類BuyStock和SellStock

public class BuyStock implements Command {
    private Stock abcStock;

    public BuyStock(Stock abcStock){
        this.abcStock = abcStock;
    }
    @Override
    public void execute() {
        abcStock.buy();
    }
}

public class SellStock implements Command {
    private Stock abcStock;

    public SellStock(Stock abcStock){
        this.abcStock = abcStock;
    }
    @Override
    public void execute() {
        abcStock.sell();
    }
}

(4)定義命令調用類Broker

public class Broker {
    private List<Command> CommandList = new ArrayList<Command>();

    public void takeCommand(Command Command){
        CommandList.add(Command);
    }

    public void placeCommands(){
        for (Command Command : CommandList) {
            Command.execute();
        }
        CommandList.clear();
    }
}

(5)使用 Broker 類來接受並執行命令:

public class Main {
    public static void main(String[] args) {
        Stock abcStock = new Stock();

        BuyStock buyStockOrder = new BuyStock(abcStock);
        SellStock sellStockOrder = new SellStock(abcStock);

        Broker broker = new Broker();
        broker.takeCommand(buyStockOrder);
        broker.takeCommand(sellStockOrder);

        broker.placeCommands();
    }
}

結果:

Stock [ Name: ABC,Quantity: 10 ] bought
Stock [ Name: ABC,Quantity: 10 ] sold

三、訪問者模式

訪問者模式將數據結構和對數據的操作分離開,使其在不改變數據結構的前提下動態添加作用於這些元素上的操作。

訪問者模式通過定義不同的訪問者實現對數據的不同操作,因此在需要給數據添加新的操作時只需為其定義一個新的訪問者即可。

訪問者模式適用於數據結構穩定但數據操作方式多變的系統中。

 

比如,有一個項目計划需要上報,項目計划包括項目名稱和項目內容,訪問者有項目經理,CEO,CTO。

(1)定義接口VIsitor:

public interface Visitor {
    void visit(ProjectElement element);
}

(2)定義VIsitor的實現類CEOVIsitor、CTOVIsitor:

public class CEOVisitor implements Visitor {
    private final static Log logger = LogFactory.getLog(CEOVisitor.class);
    @Override
    public void visit(ProjectElement element) {
        logger.info("CEO Visitor Element");
        element.signature("CEO",new Date());
        logger.info(JSON.toJSON(element));
    }
}

public class CTOVisitor implements Visitor {
    private final static Log logger = LogFactory.getLog(CTOVisitor.class);
    @Override
    public void visit(ProjectElement element) {
        logger.info("CTO Visitor Element");
        element.signature("CTO",new Date());
        logger.info(JSON.toJSON(element));
    }
}

(3)定義抽象元素Element,並定義accept()用於接收訪問者對象。

public interface Element {
    void accept(Visitor visitor);
}

(4)定義Element的實現類ProjectElement:

public class ProjectElement implements Element {
    private String projectName;
    private String projectContent;
    private String visitorName;
    private Date visitTime;

    public ProjectElement(String projectName, String projectContent) {
        this.projectName = projectName;
        this.projectContent = projectContent;
    }

    public void signature(String visitorName, Date visitTime) {
        this.visitorName = visitorName;
        this.visitTime = visitTime;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
  //省略getter、setter  
}

(5)使用訪問者模式:

public class Main {
    public static void main(String[] args) {
        Element element = new ProjectElement("ofo","清算計划");
        element.accept(new CEOVisitor());
        element.accept(new CTOVisitor());
    }
}

結果:

十二月 31, 2019 10:30:42 上午 com.jzq.sign.Visitor.CEOVisitor visit
信息: CEO Visitor Element
十二月 31, 2019 10:30:42 上午 com.jzq.sign.Visitor.CEOVisitor visit
信息: {"projectContent":"清算計划","visitTime":1577759442167,"visitorName":"CEO","projectName":"ofo"}
十二月 31, 2019 10:30:42 上午 com.jzq.sign.Visitor.CTOVisitor visit
信息: CTO Visitor Element
十二月 31, 2019 10:30:42 上午 com.jzq.sign.Visitor.CTOVisitor visit
信息: {"projectContent":"清算計划","visitTime":1577759442292,"visitorName":"CTO","projectName":"ofo"}

四、解釋器模式

解釋器模式實現了一個表達式接口,該接口解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。

注:可利用場景比較少,JAVA 中如果碰到可以用 expression4J 代替。

五、策略模式

 策略模式為同一個行為定義不同的策略,並為每種策略都實現了不同的方法。

策略模式的實現是在接口中定義不同的策略,在實現類中完成了對不同的策略下具體行為的實現。

 

以選擇旅游交通工具為例:

(1)定義TravelStrategy:

public interface TravelStrategy {
    void travelMode();
}

(2)定義TravelStrategy接口的實現類TravelByAirStrategy、TravelByCarStrategy:

public class TravelByAirStrategy implements TravelStrategy {
    private final static Log logger = LogFactory.getLog(TravelByAirStrategy.class);
    @Override
    public void travelMode() {
        logger.info("travel by air");
    }
}

public class TravelByCarStrategy implements TravelStrategy {
    private final static Log logger = LogFactory.getLog(TravelByCarStrategy.class);
    @Override
    public void travelMode() {
        logger.info("travel by car");
    }
}

(3)定義Context實現策略模式:

public class Context {
    private TravelStrategy travelStrategy;
    public TravelStrategy getTravelStrategy() {
        return travelStrategy;
    }
    public void setTravelStrategy(TravelStrategy travelStrategy) {
        this.travelStrategy = travelStrategy;
    }
    public void travelMode(){
        this.travelStrategy.travelMode();
    }
}

(4)使用策略模式:

public class Main {
    public static void main(String[] args) {
        Context context = new Context();
        TravelStrategy travelByAirStrategy = new TravelByAirStrategy();
        context.setTravelStrategy(travelByAirStrategy);
        context.travelMode();
        System.out.println("=====出行方式飛機換為汽車=====");
        TravelStrategy travelByCarStrategy = new TravelByCarStrategy();
        context.setTravelStrategy(travelByCarStrategy);
        context.travelMode();
    }
}

結果:

十二月 31, 2019 11:23:13 上午 com.jzq.sign.Strategy.TravelByAirStrategy travelMode
信息: travel by air
十二月 31, 2019 11:23:13 上午 com.jzq.sign.Strategy.TravelByCarStrategy travelMode
信息: travel by car
=====出行方式飛機換為汽車=====

六、模板模式

 模板模式在抽象類中定義了算法的結構並實現了公共部分算法,在子類中實現可變的部分並根據不同的業務需求實現不同的擴展。

 

以銀行辦理業務為例:

 (1)定義AbstractTemplate模板類:

public abstract class AbstractTemplate {
    private final static Log logger = LogFactory.getLog(AbstractTemplate.class);
    public void templateMethod(){
        //模板方法,用於核心流程和算法的實現
        checkNumber();
        queueUp();
        handleBusiness();
        serviceEvaluation();
    }
    private void checkNumber() {
        //抽號
        logger.info("checkNumber...");
    }
    private void queueUp() {
        //排隊
        logger.info("queue up");
    }
    protected abstract void handleBusiness();
    private void serviceEvaluation() {
        //服務評價
        logger.info("業務完成,請評價服務...");
    }
}

(2)定義SaveMoney、TakeMoney的業務實現:

public class SaveMoney extends AbstractTemplate {
    private final static Log logger = LogFactory.getLog(SaveMoney.class);
    @Override
    protected void handleBusiness() {
        logger.info("存錢");
    }
}

public class TakeMoney extends AbstractTemplate {
    private final static Log logger = LogFactory.getLog(TakeMoney.class);
    @Override
    protected void handleBusiness() {
        logger.info("取錢");
    }
}

(3)使用模板模式:

public class Main {
    public static void main(String[] args) {
        AbstractTemplate template1 = new TakeMoney();
        template1.templateMethod();

        AbstractTemplate template2 = new SaveMoney();
        template2.templateMethod();
    }
}

結果:

十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate checkNumber
信息: checkNumber...
十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate queueUp
信息: queue up
十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.TakeMoney handleBusiness
信息: 取錢
十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate serviceEvaluation
信息: 業務完成,請評價服務...
十二月
31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate checkNumber 信息: checkNumber... 十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate queueUp 信息: queue up 十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.SaveMoney handleBusiness 信息: 存錢 十二月 31, 2019 4:55:27 下午 com.jzq.sign.Template.AbstractTemplate serviceEvaluation 信息: 業務完成,請評價服務...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM