玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式
命令模式
- 示例
- 改進(jìn)代碼
- 命令模式
- 定義
- 意圖
- 主要解決問題
- 何時使用
- 優(yōu)缺點(diǎn)
- 玉帝傳美猴王上天
- 命令模式和策略模式的區(qū)別
示例
系統(tǒng)需要設(shè)計(jì)一個命令行界面,用戶可輸入命令來執(zhí)行某項(xiàng)功能,系統(tǒng)的功能會不斷增加,命令也會不斷的增加
如何將一項(xiàng)一項(xiàng)的功能加入到這個命令行界面?
如何讓命令行程序?qū)懞煤?#xff0c;不因功能的添加而修改,又可以靈活的加入命令和功能?
下面以奶茶店售賣奶茶為例:
服務(wù)員類:負(fù)責(zé)接待顧客售賣奶茶
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("您點(diǎn)的奶茶本店沒有。。。");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();} }
現(xiàn)在如果奶茶增加了呢,需要對服務(wù)員類中的switch語句進(jìn)行修改,但是又不想修改,該怎么做呢
改進(jìn)代碼
定義一個制作奶茶的接口,所有的奶茶實(shí)現(xiàn)它:
public interface Command {/** 制作奶茶接口 */void build(); }實(shí)現(xiàn)類:
public class AppleMilk implements Command {@Overridepublic void build() {System.out.println("開始制作蘋果奶茶。。。");} } public class PlainMilk implements Command {@Overridepublic void build() {System.out.println("開始制作原味奶茶。。。");} }現(xiàn)在又招了一個女服務(wù)員,負(fù)責(zé)接待:
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("您點(diǎn)的奶茶本店沒有。。。");}}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();} }
上面改進(jìn)之后,每增加一個新的奶茶,只需要實(shí)現(xiàn)接口即可
命令模式
定義
以命令的方式,解耦調(diào)用者和功能的具體實(shí)現(xiàn)者,降低了系統(tǒng)的耦合度,提高了靈活性
意圖
將一個請求封裝成一個對象,從而使您可以用不同的請求對客戶進(jìn)行參數(shù)化
主要解決問題
在軟件系統(tǒng)中,行為請求者與行為實(shí)現(xiàn)者通常是一種緊耦合的關(guān)系,但某些場合,比如需要對行為進(jìn)行記錄、撤銷或重做、事務(wù)等處理時,這種無法抵御變化的緊耦合的設(shè)計(jì)就不太合適
何時使用
在某些場合,比如要對行為進(jìn)行"記錄、撤銷/重做、事務(wù)"等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將"行為請求者"與"行為實(shí)現(xiàn)者"解耦?將一組行為抽象為對象,可以實(shí)現(xiàn)二者之間的松耦合
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
缺點(diǎn):
使用命令模式可能會導(dǎo)致某些系統(tǒng)有過多的具體命令類
類圖:
涉及的角色:
對應(yīng)的類如下:
Client類:
Command接口:
public interface Command {/** 執(zhí)行方法 */void execute(); }ConcreteComman實(shí)現(xiàn)類:
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() {} }玉帝傳美猴王上天
在美猴王大鬧天宮之前,玉帝命令太白金星召美猴王上天,玉帝的這一道旨意就是一個命令,而太白金星則是負(fù)責(zé)將圣旨傳到,具體的執(zhí)行者則是美猴王:
抽象接口,所有的圣旨都需要實(shí)現(xiàn)它:
具體的命令,即召美猴王上天這一個具體的圣旨:
public class SkyReportsConcreteCommand implements ImperialEdictCommand {private MonkeyKingReceiver receiver;public SkyReportsConcreteCommand(MonkeyKingReceiver receiver) {this.receiver = receiver;}@Overridepublic void command() {System.out.println("宣美猴王孫悟空上天報(bào)道!");receiver.action();} }玉皇大帝,頒布圣旨:
public class TheJadeEmperorClient {public static void main(String[] args) {System.out.println("玉皇大帝頒布一道圣旨,宣美猴王上天報(bào)道!");MonkeyKingReceiver receiver = new MonkeyKingReceiver();ImperialEdictCommand command = new SkyReportsConcreteCommand(receiver);GreatWhitePlanetInvoker invoker = new GreatWhitePlanetInvoker();invoker.setCommand(command);invoker.action();} }太白金星負(fù)責(zé)把旨意傳達(dá)給美猴王:
public class GreatWhitePlanetInvoker {private ImperialEdictCommand command;public void setCommand(ImperialEdictCommand command) {this.command = command;}/** 請求者太白金星調(diào)用此方法,要求美猴王上天 */public void action() {System.out.println("太白金星傳玉帝圣旨!");command.command();} }具體的執(zhí)行者,就是美猴王:
public class MonkeyKingReceiver {public MonkeyKingReceiver() {}public void action() {System.out.println("美猴王孫悟空上天,大鬧天宮!");} }
類圖:
命令模式和策略模式的區(qū)別
命令模式的結(jié)構(gòu)如下:
策略模式的結(jié)構(gòu)如下:
策略模式:側(cè)重的是一個行為的多個算法實(shí)現(xiàn),可互換算法,比如優(yōu)惠活動滿減和打折都是算法,可以選擇其中一個來買買買
命令模式:側(cè)重的是為多個行為提供靈活的執(zhí)行方式,比如上面的奶茶,每個顧客購買奶茶的命令都是一個行為,而不同的奶茶制作方式不一樣,則就需要靈活的去制作奶茶
總結(jié)
以上是生活随笔為你收集整理的玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jsonPath解析测试
- 下一篇: 免疫沉淀常见问题解答 | MedChem