命令模式-接收者与执行者解耦和

老板:阿飞,咱们公司又接了个新项目,一个客户,,卧室和客厅很大,电灯电视开关也不好找,所以希望制造一个遥控器来控制一些家具的开启与关闭,目前需要5个按键,卧室的灯,卧室的电视,客厅的灯,客厅的电视,在留一个预备按键。我等会把需求文档给你。 项目组长阿飞:好的,老板 项目组长阿飞:小三,来了个需求,你看下,你先设计一下架构 阿三:好的,飞哥

三天过后:飞哥,好了,你看下

先设计了一个接口,里面包含了,每一个按钮的统一行为

 1package com.commandPattern.command;
 2
 3/**
 4 * @program: testPattern
 5 * @description: 命令接口
 6 * @author: Mr.Yang
 7 * @create: 2018-12-08 13:54
 8 **/
 9public interface Command {
10
11    //执行方法
12    public void exceute();
13
14}

然后建立了一个对象,代表了空对象,什么操作也不执行

 1package com.commandPattern.command.nullCommand;
 2
 3import com.commandPattern.command.Command;
 4
 5/**
 6 * @program: testPattern
 7 * @description: 建立一个空对象,在许多设计模式种,都会看到空对象的使用,甚至有些时候,空对象本身也被视为一种设计模式
 8 * @author: Mr.Yang
 9 * @create: 2018-12-08 17:40
10 **/
11public class NullCommand implements Command {
12    public void exceute() {
13        System.out.println("什么都不做处理");
14    }
15}

灯的具体类

 1package com.commandPattern.entity;
 2
 3/**
 4 * @program: testPattern
 5 * @description: 灯的具体类
 6 * @author: Mr.Yang
 7 * @create: 2018-12-08 17:31
 8 **/
 9public class Lamp {
10    private String name;
11
12    /**
13     * name为灯的具体装饰,即为哪里的灯
14     * @param name
15     */
16    public  Lamp(String name){
17        this.name=name;
18    }
19    public void  on (){
20        System.out.println(name+"_灯打开");
21    }
22    public void off (){
23        System.out.println(name+"_灯关闭");
24    }
25}

电视的具体类

 1package com.commandPattern.entity;
 2
 3/**
 4 * @program: testPattern
 5 * @description: 电视的具体类
 6 * @author: Mr.Yang
 7 * @create: 2018-12-08 17:35
 8 **/
 9public class Tv {
10    private String name;
11    public Tv(String name){
12        this.name=name;
13    }
14    public void  on (){
15        System.out.println(name+"_电视打开");
16    }
17    public void off(){
18        System.out.println(name+"_电视关闭");
19    }
20}

关闭灯的具体命令

 1package com.commandPattern.command.off;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Lamp;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 灯关闭
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:33
11 **/
12public class LampOffCommand implements Command {
13
14    Lamp lamp;
15
16    public LampOffCommand(Lamp lamp){
17        this.lamp=lamp;
18    }
19    //灯关闭
20    public void exceute() {
21        lamp.off();
22    }
23}

打开灯的具体命令

 1package com.commandPattern.command.on;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Lamp;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 灯打开的命令
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:29
11 **/
12public class LampOnCommand implements Command {
13
14    Lamp lamp;
15    public LampOnCommand(Lamp lamp){
16        this.lamp=lamp;
17    }
18
19    //灯打开的命令
20    public void exceute() {
21        lamp.on();
22    }
23}

电视关闭的具体命令

 1package com.commandPattern.command.off;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Tv;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 电视关闭
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:36
11 **/
12public class TvOffCommand implements Command {
13    Tv tv;
14    public TvOffCommand(Tv tv){
15        this.tv=tv;
16    }
17    public void exceute() {
18        tv.off();
19    }
20}

电视打开的具体命令

 1package com.commandPattern.command.on;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Tv;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 电视打开
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:37
11 **/
12public class TvOnCommand implements Command {
13    Tv tv;
14    public TvOnCommand(Tv tv){
15        this.tv=tv;
16    }
17
18    public void exceute() {
19        tv.on();
20    }
21}

建立一个遥控器

 1package com.commandPattern.control;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.command.nullCommand.NullCommand;
 5
 6import java.util.Arrays;
 7
 8/**
 9 * @program: testPattern
10 * @description: 遥控器
11 * @author: Mr.Yang
12 * @create: 2018-12-08 17:39
13 **/
14public class RemoteControl {
15
16    Command[] onCommand;
17    Command[] offCommand;
18
19    //初始化每个操作为空操作
20    public RemoteControl(){
21        onCommand=new Command[5];
22        offCommand=new Command[5];
23        NullCommand nullCommand = new NullCommand();
24        for (int i = 0; i < 5; i++) {
25            onCommand[i]=nullCommand;
26            offCommand[i]=nullCommand;
27        }
28    }
29
30    public void setCommond(int index,Command onCommand,Command offCommand){
31        this.offCommand[index]=offCommand;
32        this.onCommand[index]=onCommand;
33    }
34
35    public void clickOn(int index){
36        onCommand[index].exceute();
37    }
38
39    public void clickOff(int index){
40        offCommand[index].exceute();
41    }
42
43    /**
44     * 输出每个按钮的具体代表类
45     * @return
46     */
47    @Override
48    public String toString() {
49        StringBuffer sb = new StringBuffer();
50        for (int i = 0; i < onCommand.length; i++) {
51            sb.append("[index : "+i+"]   ");
52            sb.append(onCommand[i].getClass().getName());
53            sb.append("    ");
54            sb.append(offCommand[i].getClass().getName());
55            sb.append("\r\n");
56        }
57        return sb.toString();
58    }
59}

测试类

 1package com.commandPattern.testPattern;
 2
 3import com.commandPattern.command.off.LampOffCommand;
 4import com.commandPattern.command.off.TvOffCommand;
 5import com.commandPattern.command.on.LampOnCommand;
 6import com.commandPattern.command.on.TvOnCommand;
 7import com.commandPattern.control.RemoteControl;
 8import com.commandPattern.entity.Lamp;
 9import com.commandPattern.entity.Tv;
10
11/**
12 * @program: test
13 * @description:
14 * @author: Mr.Yang
15 * @create: 2018-12-08 17:48
16 **/
17public class TestPattern {
18    public static void main(String[] args) {
19        RemoteControl remoteControl = new RemoteControl();
20
21        /**
22         * 创建装置到合适位置
23         */
24        Tv bedRoomTV = new Tv("卧室");
25        Tv drawiTV = new Tv("客厅");
26
27        Lamp bedRoomLamp = new Lamp("卧室");
28        Lamp drawiLamp = new Lamp("客厅");
29
30        /**
31         * 创建所有命令操作对象
32         */
33        //卧室灯关闭对象
34        LampOffCommand bedLampOffCommand = new LampOffCommand(bedRoomLamp);
35        //卧室灯打开对象
36        LampOnCommand bedLampOnCommand = new LampOnCommand(bedRoomLamp);
37        //卧室TV关闭对象
38        TvOffCommand bedTvOffCommand = new TvOffCommand(bedRoomTV);
39        //卧室TV打开对象
40        TvOnCommand bedTVcommand = new TvOnCommand(bedRoomTV);
41        //客厅灯打开对象
42        LampOnCommand drawLampOnCommand = new LampOnCommand(drawiLamp);
43        //客厅灯关闭对象
44        LampOffCommand drawLampOffCommand = new LampOffCommand(drawiLamp);
45        //客厅TV关闭对象
46        TvOffCommand drawTVOffCommand = new TvOffCommand(drawiTV);
47        //客厅TV打开对象
48        TvOnCommand drawTVOnCommand = new TvOnCommand(drawiTV);
49
50        System.out.println("---------------------------------------------未赋值之前------------------------------------------------");
51        System.out.println(remoteControl);
52        System.out.println("******************************************************************************************************");
53
54        /**
55         * //将操作对象与卡槽一一对应
56         */
57        //赋值卧室灯打开与关闭
58        remoteControl.setCommond(0,bedLampOnCommand,bedLampOffCommand);
59        //赋值卧室TV打开与关闭
60        remoteControl.setCommond(1,bedTVcommand,bedTvOffCommand);
61        //赋值客厅灯打开与关闭
62        remoteControl.setCommond(2,drawLampOnCommand,drawLampOffCommand);
63        //赋值客厅TV打开与关闭
64        remoteControl.setCommond(3,drawTVOnCommand,drawTVOffCommand);
65
66        System.out.println("---------------------------------------------赋值之后------------------------------------------------");
67        System.out.println(remoteControl);
68        System.out.println("******************************************************************************************************");
69
70
71        /**
72         * 测试每一个按钮
73         */
74        remoteControl.clickOn(0);
75        remoteControl.clickOff(0);
76
77        remoteControl.clickOn(1);
78        remoteControl.clickOff(1);
79
80        remoteControl.clickOn(2);
81        remoteControl.clickOff(2);
82
83        remoteControl.clickOn(3);
84        remoteControl.clickOff(3);
85
86
87    }
88}

测试结果

 1---------------------------------------------未赋值之前------------------------------------------------
 2[index : 0]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 3[index : 1]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 4[index : 2]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 5[index : 3]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 6[index : 4]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 7
 8******************************************************************************************************
 9---------------------------------------------赋值之后------------------------------------------------
10[index : 0]   com.commandPattern.command.on.LampOnCommand    com.commandPattern.command.off.LampOffCommand
11[index : 1]   com.commandPattern.command.on.TvOnCommand    com.commandPattern.command.off.TvOffCommand
12[index : 2]   com.commandPattern.command.on.LampOnCommand    com.commandPattern.command.off.LampOffCommand
13[index : 3]   com.commandPattern.command.on.TvOnCommand    com.commandPattern.command.off.TvOffCommand
14[index : 4]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
15
16******************************************************************************************************
17卧室_灯打开
18卧室_灯关闭
19卧室_电视打开
20卧室_电视关闭
21客厅_灯打开
22客厅_灯关闭
23客厅_电视打开
24客厅_电视关闭

阿三:飞哥,我这里使用的设计模式-命令模式, 将动作执行(LampOnCommand,TvOnCommand……)与接收者(Lamp,Tv)包装到对象里面,对外暴露的只有一个Command接口中的execute方法,其他对象不需要知道那个接收者执行了什么动作,只需要知道调用execute,就能完成一个请求的操作,这个对象,与其他对象没有关联,完全解耦和,如果需要做新增,不需要修改原有代码,拓展接收者类和动作执行类,就能实现功能。

项目组长阿飞:不错,不错,进步很大。 项目组长阿飞:第5个按钮可能需要做一个恢复上一步动作的效果,类似于CTRL+Z这个效果,你再改改把。 阿三:好的。 阿三:飞哥修改好了,你看下

命令接口新增撤销方法

 1package com.commandPattern.command;
 2
 3/**
 4 * @program: testPattern
 5 * @description: 命令接口
 6 * @author: Mr.Yang
 7 * @create: 2018-12-08 13:54
 8 **/
 9public interface Command {
10
11    //执行方法
12    public void exceute();
13
14    //撤销方法
15    public void revoke();
16
17}

建立一个空对象,实现了撤销方法

 1package com.commandPattern.command.nullCommand;
 2
 3import com.commandPattern.command.Command;
 4
 5/**
 6 * @program: testPattern
 7 * @description: 建立一个空对象,在许多设计模式种,都会看到空对象的使用,甚至有些时候,空对象本身也被视为一种设计模式
 8 * @author: Mr.Yang
 9 * @create: 2018-12-08 17:40
10 **/
11public class NullCommand implements Command {
12    public void exceute() {
13        System.out.println("什么都不做处理");
14    }
15
16    public void revoke() {
17        System.out.println("什么都不做处理");
18    }
19}

灯关闭实现了撤销方法

 1package com.commandPattern.command.off;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Lamp;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 灯关闭
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:33
11 **/
12public class LampOffCommand implements Command {
13
14    Lamp lamp;
15
16    public LampOffCommand(Lamp lamp){
17        this.lamp=lamp;
18    }
19    //灯关闭
20    public void exceute() {
21        lamp.off();
22    }
23    //执行到这个具体实现类,代表上一步是灯关闭,撤销操作即为灯打开
24    public void revoke() {
25        lamp.on();
26    }
27}

灯打开实现了撤销方法

 1package com.commandPattern.command.on;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Lamp;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 灯打开的命令
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:29
11 **/
12public class LampOnCommand implements Command {
13
14    Lamp lamp;
15    public LampOnCommand(Lamp lamp){
16        this.lamp=lamp;
17    }
18
19    //灯打开的命令
20    public void exceute() {
21        lamp.on();
22    }
23    //执行到这个具体实现类,代表上一步是灯打开,撤销操作即为灯关闭
24    public void revoke() {
25        lamp.off();
26    }
27}

电视关闭实现了撤销方法

 1package com.commandPattern.command.off;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Tv;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 电视关闭
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:36
11 **/
12public class TvOffCommand implements Command {
13    Tv tv;
14    public TvOffCommand(Tv tv){
15        this.tv=tv;
16    }
17    public void exceute() {
18        tv.off();
19    }
20    //执行到这个具体实现类,代表上一步是电视关闭,撤销操作即为电视打开
21    public void revoke() {
22        tv.on();
23    }
24}

电视打开实现了撤销方法

 1package com.commandPattern.command.on;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.entity.Tv;
 5
 6/**
 7 * @program: testPattern
 8 * @description: 电视打开
 9 * @author: Mr.Yang
10 * @create: 2018-12-08 17:37
11 **/
12public class TvOnCommand implements Command {
13    Tv tv;
14    public TvOnCommand(Tv tv){
15        this.tv=tv;
16    }
17
18    public void exceute() {
19        tv.on();
20    }
21    //执行到这个具体实现类,代表上一步是电视打开,撤销操作即为电视关闭
22    public void revoke() {
23        tv.off();
24    }
25}

遥控器类,新增变量记录上一步操作

 1package com.commandPattern.control;
 2
 3import com.commandPattern.command.Command;
 4import com.commandPattern.command.nullCommand.NullCommand;
 5
 6import java.util.Arrays;
 7
 8/**
 9 * @program: testPattern
10 * @description: 遥控器
11 * @author: Mr.Yang
12 * @create: 2018-12-08 17:39
13 **/
14public class RemoteControl {
15
16    Command[] onCommand;
17    Command[] offCommand;
18    //这个变量来记录上一个命令
19    Command upStepCommand;
20    //初始化每个操作为空操作
21    public RemoteControl(){
22        onCommand=new Command[5];
23        offCommand=new Command[5];
24        NullCommand nullCommand = new NullCommand();
25        for (int i = 0; i < 5; i++) {
26            onCommand[i]=nullCommand;
27            offCommand[i]=nullCommand;
28        }
29        upStepCommand=nullCommand;
30    }
31
32    public void setCommond(int index,Command onCommand,Command offCommand){
33        this.offCommand[index]=offCommand;
34        this.onCommand[index]=onCommand;
35    }
36    //新增upStepCommand记录上一步命令
37    public void clickOn(int index){
38        onCommand[index].exceute();
39        upStepCommand=onCommand[index];
40    }
41    //新增upStepCommand记录上一步命令
42    public void clickOff(int index){
43        offCommand[index].exceute();
44        upStepCommand=offCommand[index];
45    }
46
47    public void toUpStepClick(){
48        System.out.println("---撤销---");
49        upStepCommand.revoke();
50    }
51    /**
52     * 输出每个按钮的具体代表类
53     * @return
54     */
55    @Override
56    public String toString() {
57        StringBuffer sb = new StringBuffer();
58        for (int i = 0; i < onCommand.length; i++) {
59            sb.append("[index : "+i+"]   ");
60            sb.append(onCommand[i].getClass().getName());
61            sb.append("    ");
62            sb.append(offCommand[i].getClass().getName());
63            sb.append("\r\n");
64        }
65        return sb.toString();
66    }
67}

测试类新增撤销测试

  1package com.commandPattern.testPattern;
  2
  3import com.commandPattern.command.off.LampOffCommand;
  4import com.commandPattern.command.off.TvOffCommand;
  5import com.commandPattern.command.on.LampOnCommand;
  6import com.commandPattern.command.on.TvOnCommand;
  7import com.commandPattern.control.RemoteControl;
  8import com.commandPattern.entity.Lamp;
  9import com.commandPattern.entity.Tv;
 10
 11/**
 12 * @program: test
 13 * @description:
 14 * @author: Mr.Yang
 15 * @create: 2018-12-08 17:48
 16 **/
 17public class TestPattern {
 18    public static void main(String[] args) {
 19        RemoteControl remoteControl = new RemoteControl();
 20
 21        /**
 22         * 创建装置到合适位置
 23         */
 24        Tv bedRoomTV = new Tv("卧室");
 25        Tv drawiTV = new Tv("客厅");
 26
 27        Lamp bedRoomLamp = new Lamp("卧室");
 28        Lamp drawiLamp = new Lamp("客厅");
 29
 30        /**
 31         * 创建所有命令操作对象
 32         */
 33        //卧室灯关闭对象
 34        LampOffCommand bedLampOffCommand = new LampOffCommand(bedRoomLamp);
 35        //卧室灯打开对象
 36        LampOnCommand bedLampOnCommand = new LampOnCommand(bedRoomLamp);
 37        //卧室TV关闭对象
 38        TvOffCommand bedTvOffCommand = new TvOffCommand(bedRoomTV);
 39        //卧室TV打开对象
 40        TvOnCommand bedTVcommand = new TvOnCommand(bedRoomTV);
 41        //客厅灯打开对象
 42        LampOnCommand drawLampOnCommand = new LampOnCommand(drawiLamp);
 43        //客厅灯关闭对象
 44        LampOffCommand drawLampOffCommand = new LampOffCommand(drawiLamp);
 45        //客厅TV关闭对象
 46        TvOffCommand drawTVOffCommand = new TvOffCommand(drawiTV);
 47        //客厅TV打开对象
 48        TvOnCommand drawTVOnCommand = new TvOnCommand(drawiTV);
 49
 50        System.out.println("---------------------------------------------未赋值之前------------------------------------------------");
 51        System.out.println(remoteControl);
 52        System.out.println("******************************************************************************************************");
 53
 54        /**
 55         * //将操作对象与卡槽一一对应
 56         */
 57        //赋值卧室灯打开与关闭
 58        remoteControl.setCommond(0,bedLampOnCommand,bedLampOffCommand);
 59        //赋值卧室TV打开与关闭
 60        remoteControl.setCommond(1,bedTVcommand,bedTvOffCommand);
 61        //赋值客厅灯打开与关闭
 62        remoteControl.setCommond(2,drawLampOnCommand,drawLampOffCommand);
 63        //赋值客厅TV打开与关闭
 64        remoteControl.setCommond(3,drawTVOnCommand,drawTVOffCommand);
 65
 66        System.out.println("---------------------------------------------赋值之后------------------------------------------------");
 67        System.out.println(remoteControl);
 68        System.out.println("******************************************************************************************************");
 69
 70
 71        /**
 72         * 测试每一个按钮
 73         */
 74        remoteControl.clickOn(0);
 75        remoteControl.clickOff(0);
 76
 77        //撤销一次
 78        remoteControl.toUpStepClick();
 79        System.out.println("\r\n");
 80
 81        //撤销一次
 82        remoteControl.toUpStepClick();
 83        System.out.println("\r\n");
 84
 85        remoteControl.clickOn(1);
 86        remoteControl.clickOff(1);
 87
 88        //撤销一次
 89        remoteControl.toUpStepClick();
 90        System.out.println("\r\n");
 91
 92        remoteControl.clickOn(2);
 93        remoteControl.clickOff(2);
 94
 95        //撤销一次
 96        remoteControl.toUpStepClick();
 97        System.out.println("\r\n");
 98
 99        remoteControl.clickOn(3);
100        remoteControl.clickOff(3);
101
102        //撤销一次
103        remoteControl.toUpStepClick();
104        System.out.println("\r\n");
105
106    }
107}

修改之后的测试结果

 1---------------------------------------------未赋值之前------------------------------------------------
 2[index : 0]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 3[index : 1]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 4[index : 2]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 5[index : 3]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 6[index : 4]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
 7
 8******************************************************************************************************
 9---------------------------------------------赋值之后------------------------------------------------
10[index : 0]   com.commandPattern.command.on.LampOnCommand    com.commandPattern.command.off.LampOffCommand
11[index : 1]   com.commandPattern.command.on.TvOnCommand    com.commandPattern.command.off.TvOffCommand
12[index : 2]   com.commandPattern.command.on.LampOnCommand    com.commandPattern.command.off.LampOffCommand
13[index : 3]   com.commandPattern.command.on.TvOnCommand    com.commandPattern.command.off.TvOffCommand
14[index : 4]   com.commandPattern.command.nullCommand.NullCommand    com.commandPattern.command.nullCommand.NullCommand
15
16******************************************************************************************************
17卧室_灯打开
18卧室_灯关闭
19---撤销---
20卧室_灯打开
21
22
23---撤销---
24卧室_灯打开
25
26
27卧室_电视打开
28卧室_电视关闭
29---撤销---
30卧室_电视打开
31
32
33客厅_灯打开
34客厅_灯关闭
35---撤销---
36客厅_灯打开
37
38
39客厅_电视打开
40客厅_电视关闭
41---撤销---
42客厅_电视打开

项目组长阿飞:不错,不错,以后给你涨工资。

本文分享自微信公众号 - JAVA知识总结与分享(summing_up_sharing)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券