介紹java
命令模式是一種行爲型設計模式。在命令模式中,全部的請求都會被包裝成爲一個對象。設計模式
參考了一下其餘關於命令模式的文章,其中有談到說是能夠用不一樣的請求對客戶進行參數化。對這句話的理解是,由於將請求封裝成爲對象,因此客戶的全部操做,其實就是多個命令類的對象而已,即參數化了。
命令模式的最大的特色就是將請求的調用者與請求的最終執行者進行了解耦。調用者須要關心的僅僅是請求對象是否被執行了,對於請求對象是如何執行的,對什麼進行操做的,通通不須要關心。ide
原理:命令模式中,通常有以下幾個角色:ui
適用場景:涉及到「命令」、「操做」或者「控制」的場景,通常都是命令模式的適用場景。this
命令接口:spa
/** * @program: test * @description: 命令 * @author: xingcheng * @create: 2018-09-02 15:16 **/ public interface Command { /** * 執行命令 */ void execute(); }
定義receiver:設計
/** * @program: test * @description: 水果 * @author: xingcheng * @create: 2018-09-02 15:18 **/ public class Fruit { /** * 點一份水果 */ void orderFruit(){ System.out.println("來一份水果"); } /** * 取消水果 */ void cancelFruit(){ System.out.println("取消水果"); } } /** * @program: test * @description: 牛奶 * @author: xingcheng * @create: 2018-09-02 15:22 **/ public class Milk { /** * 點一份牛奶 */ void orderMilk(){ System.out.println("來一份牛奶"); } /** * 取消牛奶 */ void cancelMilk(){ System.out.println("取消牛奶"); } } /** * @program: test * @description: 甜點 * @author: xingcheng * @create: 2018-09-02 15:17 **/ public class Mousse { /** * 點一份甜點 */ void orderMousse(){ System.out.println("來一份甜點"); } /** * 取消甜點 */ void cancelMousse(){ System.out.println("取消甜點"); } }
定義具體命令:code
/** * @program: test * @description: 點一份水果 * @author: xingcheng * @create: 2018-09-02 15:29 **/ public class OrderFruit implements Command{ private Fruit fruit; public OrderFruit(Fruit fruit) { this.fruit = fruit; } /** * 執行命令 */ @Override public void execute() { fruit.orderFruit(); } } /** * @program: test * @description: 點一份牛奶 * @author: xingcheng * @create: 2018-09-02 15:25 **/ public class OrderMilk implements Command{ private Milk milk; public OrderMilk(Milk milk) { this.milk = milk; } /** * 執行命令 */ @Override public void execute() { milk.orderMilk(); } } /** * @program: test * @description: 點一份甜點 * @author: xingcheng * @create: 2018-09-02 15:31 **/ public class OrderMousse implements Command{ private Mousse mousse; public OrderMousse(Mousse mousse) { this.mousse = mousse; } /** * 執行命令 */ @Override public void execute() { mousse.orderMousse(); } } /** * @program: test * @description: 取消水果 * @author: xingcheng * @create: 2018-09-02 15:30 **/ public class CancelFruit implements Command { private Fruit fruit; public CancelFruit(Fruit fruit) { this.fruit = fruit; } /** * 執行命令 */ @Override public void execute() { fruit.cancelFruit(); } } /** * @program: test * @description: 取消牛奶 * @author: xingcheng * @create: 2018-09-02 15:27 **/ public class CancelMilk implements Command{ private Milk milk; public CancelMilk(Milk milk) { this.milk = milk; } /** * 執行命令 */ @Override public void execute() { milk.cancelMilk(); } } /** * @program: test * @description: 取消甜點 * @author: xingcheng * @create: 2018-09-02 15:32 **/ public class CancelMousse implements Command { private Mousse mousse; public CancelMousse(Mousse mousse) { this.mousse = mousse; } /** * 執行命令 */ @Override public void execute() { mousse.cancelMousse(); } }
定義菜單(invoker)對象
/** * @program: test * @description: 菜單 * @author: xingcheng * @create: 2018-09-02 15:36 **/ public class Menu { private List<Command> commands; public Menu() { this.commands = new ArrayList<>(); } /** * 記錄顧客須要什麼 */ public void writeMenu(Command command){ commands.add(command); } /** * 將菜單交給廚師 */ public void giveCooker(){ if (commands != null && commands.size() > 0){ commands.forEach(command -> command.execute()); } } }
顧客購買:blog
/** * @program: test * @description: 顧客 * @author: xingcheng * @create: 2018-09-02 15:34 **/ public class Consumer { public static void main(String[] args) { Fruit fruit = new Fruit(); Milk milk = new Milk(); Mousse mousse = new Mousse(); // 店小二記錄菜單 System.out.println("店小二記錄菜單----------------------------------------------"); Menu menu = new Menu(); menu.writeMenu(new OrderFruit(fruit)); menu.writeMenu(new OrderMilk(milk)); menu.writeMenu(new OrderMousse(mousse)); // 店小二將菜單交給廚師 menu.giveCooker(); // 顧客取消菜單--太貴了不吃了╭(╯^╰)╮ System.out.println("顧客取消菜單--太貴了不吃了╭(╯^╰)╮----------------------------"); Menu menuCancel = new Menu(); menuCancel.writeMenu(new CancelFruit(fruit)); menuCancel.writeMenu(new CancelMilk(milk)); menuCancel.writeMenu(new CancelMousse(mousse)); menuCancel.giveCooker(); System.out.println("宏命令----------------------------"); List<Command> commands = new ArrayList<>(); commands.add(new CancelFruit(fruit)); commands.add(new CancelMilk(milk)); commands.add(new CancelMousse(mousse)); MutilCommand mutilCommand = new MutilCommand(commands); mutilCommand.giveCooker(); } }
結果:
命令模式中有一種擴展,叫作宏命令,能同時進行一組命令的執行。好比遙控器只存在兩個按鍵,一個控制全部電器的開啓,一個控制全部電器的關閉。那麼咱們不須要改動已有的代碼,只要擴展一個組合命令類,其中包含多個命令便可。
/** * @program: test * @description: 宏命令(組合命令) * @author: xingcheng * @create: 2018-09-02 15:59 **/ public class MutilCommand { private List<Command> commands; public MutilCommand(List<Command> commands) { this.commands = commands; } /** * 記錄顧客須要什麼 */ public void writeMenu(Command command){ commands.add(command); } /** * 將菜單交給廚師 */ public void giveCooker(){ if (commands != null && commands.size() > 0){ commands.forEach(command -> command.execute()); } } }
命令模式的核心思想就是將命令或者請求封裝成對象,分離請求調用者和請求最終執行者。
優勢:將請求調用者和執行者解耦,適用於底層接口封裝,能夠經過只增長類就能夠實現接口擴展,不須要修改原來的代碼。
缺點:若是存在較多的命令或者請求,須要較多的命令類。