码迷,mamicode.com
首页 > 其他好文 > 详细

案例分析:设计模式与代码的结构特性

时间:2019-12-07 12:10:05      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:ati   需要   设置   invoke   strong   客户端   好处   apple   指定   

命令模式

       命令模式(Command Pattern)将一个请求封装为一个对象,从而可以使用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销操作。命令模式又称为动作(Action)模式或者事务(Transaction)模式。

 

命令模式的适用性:

  1)系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。

  2)系统需要在不同的时间指定请求、将请求排队和执行请求。

  3)系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

  4)系统需要将一组操作组合在一起,即支持宏命令。

 
命令模式的优点:

  1) 降低系统的耦合度:Command模式将调用操作的对象与知道如何实现该操作的对象解耦。

  2) Command是头等的对象。它们可像其他的对象一样被操纵和扩展。

  3) 组合命令:你可将多个命令装配成一个组合命令,即可以比较容易地设计一个命令队列和宏命令。一般说来,组合命令是Composite模式的一个实例。

  4) 增加新的Command很容易,因为这无需改变已有的类。

  5)可以方便地实现对请求的Undo和Redo。

 

命令模式的缺点:

  使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

 

命令模式的结构:

技术图片

  抽象命令类(Command):声明执行操作的接口。调用接收者相应的操作,以实现执行的方法Execute。

  具体命令类(ConcreteCommand):创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。 

  调用者(Invoker):要求该命令执行这个请求。通常会持有命令对象,可以持有很多的命令对象。

  接收者(Receiver):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的相应功能。 

  客户类(Client):创建具体的命令对象,并且设置命令对象的接收者。真正使用命令的客户端是从Invoker来触发执行。 

 

案例:

  家电遥控器就是一个典型的命令模式应用实例。

  接收者(Receiver):门、电灯、电脑。

 1 package com.zhy.pattern.command;
 2 /**
 3  * 门
 4  * @author zhy
 5  *
 6  */
 7 public class Door
 8 {
 9     public void open()
10     {
11         System.out.println("打开门");
12     }
13  
14     public void close()
15     {
16         System.out.println("关闭门");
17     }
18 }
 1 package com.zhy.pattern.command;
 2  
 3 /**
 4  * 电灯
 5  * @author zhy
 6  *
 7  */
 8 public class Light
 9 {
10     public void on()
11     {
12         System.out.println("打开电灯");
13     }
14  
15     public void off()
16     {
17         System.out.println("关闭电灯");
18     }
19 }
 1 package com.zhy.pattern.command;
 2 /**
 3  * 电脑
 4  * @author zhy
 5  *
 6  */
 7 public class Computer
 8 {
 9     public void on()
10     {
11         System.out.println("打开电脑");
12     }
13     
14     public void off()
15     {
16         System.out.println("关闭电脑");
17     }
18 }

  抽象命令类(Command):

1 package com.zhy.pattern.command;
2  
3 public interface Command
4 {
5     public void execute();
6 }

  具体命令类(ConcreteCommand):

 1 /**
 2  * 关闭电灯的命令
 3  * @author zhy
 4  *
 5  */
 6 public class LightOffCommond implements Command
 7 {
 8     private Light light ; 
 9     
10     public LightOffCommond(Light light)
11     {
12         this.light = light;
13     }
14  
15     @Override
16     public void execute()
17     {
18         light.off();
19     } 
20 }
21 
22 /**
23  * 打开电灯的命令
24  * @author zhy
25  *
26  */
27 public class LightOnCommond implements Command
28 {
29     private Light light ; 
30     
31     public LightOnCommond(Light light)
32     {
33         this.light = light;
34     }
35  
36     @Override
37     public void execute()
38     {
39         light.on();
40     }
41 }
42 
43 package com.zhy.pattern.command;
44  
45 /**
46  * 开电脑的命令
47  * @author zhy
48  *
49  */
50 public class ComputerOnCommond implements Command
51 {
52     private Computer computer ; 
53     
54     public ComputerOnCommond( Computer computer)
55     {
56         this.computer = computer;
57     }
58  
59     @Override
60     public void execute()
61     {
62         computer.on();
63     } 
64 }
65 
66 package com.zhy.pattern.command;
67  
68 /**
69  * 关电脑的命令
70  * @author zhy
71  *
72  */
73 public class ComputerOffCommond implements Command
74 {
75     private Computer computer ; 
76     
77     public ComputerOffCommond( Computer computer)
78     {
79         this.computer = computer;
80     }
81  
82     @Override
83     public void execute()
84     {
85         computer.off();
86     } 
87 }

  调用者(Invoker):遥控器有9个按钮,提供了设置每个按钮的功能和点击的方法。

 1 package com.zhy.pattern.command;
 2  
 3 /**
 4  * 控制器面板,一共有9个按钮
 5  * 
 6  * @author zhy
 7  * 
 8  */
 9 public class ControlPanel
10 {
11     private static final int CONTROL_SIZE = 9;
12     private Command[] commands;
13  
14     public ControlPanel()
15     {
16         commands = new Command[CONTROL_SIZE];
17         /**
18          * 初始化所有按钮指向空对象
19          */
20         for (int i = 0; i < CONTROL_SIZE; i++)
21         {
22             commands[i] = new NoCommand();
23         }
24     }
25  
26     /**
27      * 设置每个按钮对应的命令
28      * @param index
29      * @param command
30      */
31     public void setCommand(int index, Command command)
32     {
33         commands[index] = command;
34     }
35  
36     /**
37      * 模拟点击按钮
38      * @param index
39      */
40     public void keyPressed(int index)
41     {
42         commands[index].execute();
43     }
44 }

  使用了一个NoCommand对象,叫做空对象,这个对象的好处就是,我们不用执行前都判断个if(!=null),并且提供了一致的操作:

1 public class NoCommand implements Command
2 {
3     @Override
4     public void execute()
5     {
6  
7     }
8 }

  可以看到任意按钮可以随意配置任何命令,不用每次变一下需求就要改代码了,而是实现用户个性化;我们还可以配置到一个配置文件中实现完全的解耦。

  多态机制:遥控器使用统一的命令接口,通过发出不同命令对不同的家电进行控制。

  模块封装:遥控器封装成一个类,各电器封装成一个类,命令封装成一个类,客户封装成一个类。

  耦合度:动作请求者与动作执行者完全解耦,上例中遥控器的按钮和电器之间不存在直接关系。

  源代码:https://github.com/youlookwhat/DesignPattern

案例分析:设计模式与代码的结构特性

标签:ati   需要   设置   invoke   strong   客户端   好处   apple   指定   

原文地址:https://www.cnblogs.com/haorw/p/12001255.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!