玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式
命令模式
- 示例
- 改進代碼
- 命令模式
- 定義
- 意圖
- 主要解決問題
- 何時使用
- 優缺點
- 玉帝傳美猴王上天
- 命令模式和策略模式的區別
示例
系統需要設計一個命令行界面,用戶可輸入命令來執行某項功能,系統的功能會不斷增加,命令也會不斷的增加
如何將一項一項的功能加入到這個命令行界面?
如何讓命令行程序寫好后,不因功能的添加而修改,又可以靈活的加入命令和功能?
下面以奶茶店售賣奶茶為例:
服務員類:負責接待顧客售賣奶茶
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 {@Overridepublic void build() {System.out.println("開始制作蘋果奶茶。。。");} } public class PlainMilk implements Command {@Overridepublic 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();} }
上面改進之后,每增加一個新的奶茶,只需要實現接口即可
命令模式
定義
以命令的方式,解耦調用者和功能的具體實現者,降低了系統的耦合度,提高了靈活性
意圖
將一個請求封裝成一個對象,從而使您可以用不同的請求對客戶進行參數化
主要解決問題
在軟件系統中,行為請求者與行為實現者通常是一種緊耦合的關系,但某些場合,比如需要對行為進行記錄、撤銷或重做、事務等處理時,這種無法抵御變化的緊耦合的設計就不太合適
何時使用
在某些場合,比如要對行為進行"記錄、撤銷/重做、事務"等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將"行為請求者"與"行為實現者"解耦?將一組行為抽象為對象,可以實現二者之間的松耦合
優缺點
優點:
缺點:
使用命令模式可能會導致某些系統有過多的具體命令類
類圖:
涉及的角色:
對應的類如下:
Client類:
Command接口:
public interface Command {/** 執行方法 */void execute(); }ConcreteComman實現類:
public class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic 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 class SkyReportsConcreteCommand implements ImperialEdictCommand {private MonkeyKingReceiver receiver;public SkyReportsConcreteCommand(MonkeyKingReceiver receiver) {this.receiver = receiver;}@Overridepublic 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设计模式:命令模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jsonPath解析测试
- 下一篇: 免疫沉淀常见问题解答 | MedChem