ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式

2021-04-17 11:03:48  阅读:186  来源: 互联网

标签:Java void System 玉帝传 command 奶茶 println 设计模式 public


目录

示例

系统需要设计一个命令行界面,用户可输入命令来执行某项功能,系统的功能会不断增加,命令也会不断的增加
如何将一项一项的功能加入到这个命令行界面?
如何让命令行程序写好后,不因功能的添加而修改,又可以灵活的加入命令和功能?
下面以奶茶店售卖奶茶为例:

public class MashedTaroMilk {

    public void build() {
        System.out.println("奶茶师傅制作芋泥啵啵奶茶。。。");
    }
}
public class StrawBerryMilk {
    public void build() {
        System.out.println("奶茶师傅制作草莓奶茶。。。");
    }
}

服务员类:负责接待顾客售卖奶茶

public class Waiter {
    public void receiver(String command) {
        System.out.println("您选择了:" + command);
        switch (command) {
            case "芋泥啵啵奶茶" :
                new MashedTaroMilk().build();
                break;
            case "草莓奶茶" :
                new StrawBerryMilk().build();
                break;
            default :
                System.out.println("您点的奶茶本店没有。。。");
                break;
        }
    }

    public void showMenu() {
        System.out.println("您好,本店有以下奶茶:");
        System.out.println("\t芋泥啵啵奶茶");
        System.out.println("\t草莓奶茶");
    }
}

测试类:

public class Client {

    public static void main(String[] args) {
        waiter();
    }

    public static  void waiter() {
        Waiter waiter = new Waiter();
        waiter.showMenu();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择:");
        String chooseMilk = scanner.nextLine();
        waiter.receiver(chooseMilk);
        scanner.close();
    }
}

在这里插入图片描述
现在如果奶茶增加了呢,需要对服务员类中的switch语句进行修改,但是又不想修改,该怎么做呢

改进代码

定义一个制作奶茶的接口,所有的奶茶实现它:

public interface Command {
    /** 制作奶茶接口 */
    void build();
}

实现类:

public class AppleMilk implements Command {
    @Override
    public void build() {
        System.out.println("开始制作苹果奶茶。。。");
    }
}
public class PlainMilk implements Command {
    @Override
    public void build() {
        System.out.println("开始制作原味奶茶。。。");
    }
}

现在又招了一个女服务员,负责接待:

public class Waitress {

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

    public void addMilk(String name, Command command) {
        map.put(name, command);
    }

    public void receiver(String command) {
        System.out.println("您选择了:" + command);
        Command command1 = map.get(command);
        if (command1 != null) {
            command1.build();
        } else {
            System.out.println("您点的奶茶本店没有。。。");
        }
    }

    public void showMenu() {
        System.out.println("您好,本店有以下奶茶:");
        map.keySet().forEach((item)->{
            System.out.println("\t" + item);
        });
    }
}

测试类:

public class Client {

    public static void main(String[] args) {
        waitress();
    }

    public static void waitress() {
        Waitress waitress = new Waitress();
        waitress.addMilk("苹果奶茶", new AppleMilk());
        waitress.addMilk("原味奶茶", new PlainMilk());
        waitress.showMenu();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择:");
        String chooseMilk = scanner.nextLine();
        waitress.receiver(chooseMilk);
        scanner.close();
    }
}

在这里插入图片描述
上面改进之后,每增加一个新的奶茶,只需要实现接口即可

命令模式

定义

以命令的方式,解耦调用者和功能的具体实现者,降低了系统的耦合度,提高了灵活性

意图

将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化

主要解决问题

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适

何时使用

在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合

优缺点

优点:

  1. 降低了系统的耦合度
  2. 提高了灵活性

缺点:
使用命令模式可能会导致某些系统有过多的具体命令类

类图:
在这里插入图片描述
涉及的角色:

  1. 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者
  2. 命令(Command)角色:声明了一个给所有具体命令类的抽象接口,通常由接口或者抽象类实现
  3. 具体命令(ConcreteCommand)角色:定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操作,execute()方法通常叫做执行方法
  4. 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法
  5. 接收者(Receiver)角色:负责具体实施和执行一个请求,任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法

对应的类如下:
Client类:

public class Client {

    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Command command = new ConcreteCommand(receiver);
        Invoker invoker = new Invoker(command);
        invoker.action();
    }
}

Command接口:

public interface Command {

    /** 执行方法 */
    void execute();
}

ConcreteComman实现类:

public class ConcreteCommand implements Command {

    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        System.out.println("do something......");
        receiver.action();
    }
}

Invoker类:

public class Invoker {

    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    /** 行动方法 */
    public void action() {
        command.execute();
    }
}

Receiver类:

public class Receiver {

    public Receiver() {

    }

    /** 行动方法 */
    public void action() {

    }
}

玉帝传美猴王上天

在美猴王大闹天宫之前,玉帝命令太白金星召美猴王上天,玉帝的这一道旨意就是一个命令,而太白金星则是负责将圣旨传到,具体的执行者则是美猴王:
抽象接口,所有的圣旨都需要实现它:

public interface ImperialEdictCommand {

    /** 抽象圣旨,具体圣旨都必须具备的接口 */
    void command();
}

具体的命令,即召美猴王上天这一个具体的圣旨:

public class SkyReportsConcreteCommand implements ImperialEdictCommand {

    private MonkeyKingReceiver receiver;

    public SkyReportsConcreteCommand(MonkeyKingReceiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void command() {
        System.out.println("宣美猴王孙悟空上天报道!");
        receiver.action();
    }
}

玉皇大帝,颁布圣旨:

public class TheJadeEmperorClient {

    public static void main(String[] args) {
        System.out.println("玉皇大帝颁布一道圣旨,宣美猴王上天报道!");
        MonkeyKingReceiver receiver = new MonkeyKingReceiver();
        ImperialEdictCommand command = new SkyReportsConcreteCommand(receiver);
        GreatWhitePlanetInvoker invoker = new GreatWhitePlanetInvoker();
        invoker.setCommand(command);
        invoker.action();
    }
}

太白金星负责把旨意传达给美猴王:

public class GreatWhitePlanetInvoker {

    private ImperialEdictCommand command;

    public void setCommand(ImperialEdictCommand command) {
        this.command = command;
    }

    /** 请求者太白金星调用此方法,要求美猴王上天 */
    public void action() {
        System.out.println("太白金星传玉帝圣旨!");
        command.command();
    }
}

具体的执行者,就是美猴王:

public class MonkeyKingReceiver {

    public MonkeyKingReceiver() {

    }
    public void action() {
        System.out.println("美猴王孙悟空上天,大闹天宫!");
    }
}

在这里插入图片描述
类图:
在这里插入图片描述

命令模式和策略模式的区别

命令模式的结构如下:
在这里插入图片描述
策略模式的结构如下:
在这里插入图片描述
策略模式:侧重的是一个行为的多个算法实现,可互换算法,比如优惠活动满减和打折都是算法,可以选择其中一个来买买买

命令模式:侧重的是为多个行为提供灵活的执行方式,比如上面的奶茶,每个顾客购买奶茶的命令都是一个行为,而不同的奶茶制作方式不一样,则就需要灵活的去制作奶茶

标签:Java,void,System,玉帝传,command,奶茶,println,设计模式,public
来源: https://www.cnblogs.com/fox2said/p/14669700.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有