JAVA【设计模式】命令模式

一、定义

在这里插入图片描述
命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求过程分隔开。这样两者之间通过命令对象进行沟通,便于将命令对象进行储存、传递,增强。

二、示例:

模拟场景:
1、餐厅点菜,菜品分类为:⼭东(鲁菜)、四川(川菜)、江苏(苏菜)、⼴东(粤菜)、福建(闽菜)、浙江(浙菜)、湖南(湘菜)等,每个菜肴都有对应的厨师炒出来,例如湖南厨师炒湘菜,广东厨师炒粤菜。客户向店小二提出炒什么菜肴的请求,就会有对应的厨师去处理。
在这里插入图片描述

传统编码

通过if实现,客气请求不同的类型,炒出什么样的菜。例如类型增多,代码会变的很臃肿

package com.qf.design.behavior.command.tradition;


import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class XiaoER {
    private Logger logger= LoggerFactory.getLogger(XiaoER.class);

    private Map<Integer,String> map=new HashMap<>();

    public void order(int cusine){
        //传统的编码方式所有的情况都在一个方法下面
        if (cusine==1){
            map.put(1, "⼴东厨师,烹饪鲁菜,宫廷最⼤菜系,以孔府⻛味为⻰头");
        }

        if (cusine==2){
            map.put(2, "江苏厨师,烹饪苏菜,宫廷第⼆⼤菜系,古今国宴上最受⼈欢迎的菜系");
        }

        if (cusine==3){
            map.put(3, "⼭东厨师,烹饪鲁菜,宫廷最⼤菜系,以孔府⻛味为⻰头");
        }

        if (cusine==4){
            map.put(4, "四川厨师,烹饪川菜,中国最有特⾊的菜系,也是⺠间最⼤菜系。");
        }
    }

    public void placeOrder(){
        logger.info("菜单{}", JSON.toJSONString(map));
    }
}

测试:ApiTest

package com.qf.design.behavior.command.tradition;

public class ApiTest {
    public static void main(String[] args) {
        XiaoER xiaoER=new XiaoER();
        xiaoER.order(1);
        xiaoER.order(2);
        xiaoER.order(3);
        xiaoER.order(4);
        xiaoER.placeOrder();
    }
}

命令模式设计

定义做菜的接口,由各个厨师具体实现

package com.qf.design.behavior.command.design.cook;

public interface ICook {

    /**
     * 做菜
     */
    void cook();
}

四川厨师

package com.qf.design.behavior.command.design.cook.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.tradition.XiaoER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SiChuangCookImpl implements ICook {

    private Logger logger= LoggerFactory.getLogger(XiaoER.class);
    @Override
    public void cook() {
        logger.info("四川厨师,烹饪川菜,中国最有特⾊的菜系,也是⺠间最⼤菜系。");
    }
}

⼭东厨师

package com.qf.design.behavior.command.design.cook.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.tradition.XiaoER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShangDongCookImpl implements ICook {

    private Logger logger= LoggerFactory.getLogger(XiaoER.class);
    @Override
    public void cook() {
        logger.info("⼭东厨师,烹饪鲁菜,宫廷最⼤菜系,以孔府⻛味为⻰头");
    }
}

江苏厨师

package com.qf.design.behavior.command.design.cook.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.tradition.XiaoER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JiangSuCookImpl implements ICook {

    private Logger logger= LoggerFactory.getLogger(XiaoER.class);
    @Override
    public void cook() {
        logger.info("江苏厨师,烹饪苏菜,宫廷第⼆⼤菜系,古今国宴上最受⼈欢迎的菜系");
    }
}

⼴东厨师

package com.qf.design.behavior.command.design.cook.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.tradition.XiaoER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GuangDongCookImpl implements ICook {

    private Logger logger= LoggerFactory.getLogger(XiaoER.class);
    @Override
    public void cook() {
        logger.info("⼴东厨师,烹饪鲁菜,宫廷最⼤菜系,以孔府⻛味为⻰头");
    }
}

定义每个菜肴的接口,由各个菜肴具体实现

package com.qf.design.behavior.command.design.cusine;

public interface ICusine {
    void cook();
}

四川菜

package com.qf.design.behavior.command.design.cusine.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.design.cusine.ICusine;

public class SiChuangCusineImpl implements ICusine {
    private ICook cook;

    public SiChuangCusineImpl(ICook cook){
        this.cook=cook;
    }
    @Override
    public void cook() {
        cook.cook();
    }
}

山东菜

package com.qf.design.behavior.command.design.cusine.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.design.cusine.ICusine;

public class ShangDongCusineImpl implements ICusine {
    private ICook cook;

    public ShangDongCusineImpl(ICook cook){
        this.cook=cook;
    }
    @Override
    public void cook() {
        cook.cook();
    }
}

江苏菜

package com.qf.design.behavior.command.design.cusine.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.design.cusine.ICusine;

public class JiangSuCusineImpl implements ICusine {
    private ICook cook;

    public JiangSuCusineImpl(ICook cook){
        this.cook=cook;
    }
    @Override
    public void cook() {
        cook.cook();
    }
}

粤菜

package com.qf.design.behavior.command.design.cusine.impl;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.design.cusine.ICusine;

public class GuangdongCusineImpl implements ICusine {
    private ICook cook;

    public GuangdongCusineImpl(ICook cook){
        this.cook=cook;
    }
    @Override
    public void cook() {
        cook.cook();
    }
}

店小二负责接受客人的点单信息,转发至厨师们去实现

package com.qf.design.behavior.command.design;

import com.qf.design.behavior.command.design.cusine.ICusine;

import java.util.ArrayList;
import java.util.List;

public class Xiaoer {
    private List<ICusine> cusineList=new ArrayList<>();

    public void order(ICusine cusine){
        cusineList.add(cusine);
    }

    public synchronized void placeOrder(){
        for (ICusine iCusine : cusineList) {
            iCusine.cook();
        }

        cusineList.clear();
    }
}

测试:ApiTest

package com.qf.design.behavior.command.design;

import com.qf.design.behavior.command.design.cook.ICook;
import com.qf.design.behavior.command.design.cook.impl.GuangDongCookImpl;
import com.qf.design.behavior.command.design.cook.impl.JiangSuCookImpl;
import com.qf.design.behavior.command.design.cook.impl.ShangDongCookImpl;
import com.qf.design.behavior.command.design.cook.impl.SiChuangCookImpl;
import com.qf.design.behavior.command.design.cusine.ICusine;
import com.qf.design.behavior.command.design.cusine.impl.GuangdongCusineImpl;
import com.qf.design.behavior.command.design.cusine.impl.JiangSuCusineImpl;
import com.qf.design.behavior.command.design.cusine.impl.ShangDongCusineImpl;
import com.qf.design.behavior.command.design.cusine.impl.SiChuangCusineImpl;

public class ApiTest {
    public static void main(String[] args) {
        ICook siChuangCook = new SiChuangCookImpl();
        ICook JiangSuCookCook = new JiangSuCookImpl();
        ICook ShangDongCookCook = new ShangDongCookImpl();
        ICook GuangDongCook = new GuangDongCookImpl();

        ICusine siChuangCusine = new SiChuangCusineImpl(siChuangCook);
        ICusine jiangSuCusine = new JiangSuCusineImpl(JiangSuCookCook);
        ICusine guangdongCusine = new GuangdongCusineImpl(GuangDongCook);
        ICusine shangDongCusine = new ShangDongCusineImpl(ShangDongCookCook);

        Xiaoer xiaoer = new Xiaoer();
        xiaoer.order(siChuangCusine);
        xiaoer.order(jiangSuCusine);
        xiaoer.order(guangdongCusine);
        xiaoer.order(shangDongCusine);

        xiaoer.placeOrder();

    }
}

UML关系图

在这里插入图片描述
总结:
从以上的内容和例⼦可以感受到,命令模式的使⽤场景需要分为三个⽐较⼤的块; 命令 、 实现 、调⽤者 ,⽽这三块内容的拆分也是选择适合场景的关键因素,经过这样的拆分可以让逻辑具备单⼀职责的性质,便于扩展。

通过这样的实现⽅式与if语句相⽐,降低了耦合性也⽅便其他的命令和实现的扩展。但同时这样的设计模式也带来了⼀点问题,就是在各种命令与实现的组合下,会扩展出很多的实现类,需要进⾏管理。

posted @ 2022-08-30 22:40  雾托邦  阅读(99)  评论(0编辑  收藏  举报