Command设计模式

来源:互联网 发布:c语言的gis开源项目 编辑:程序博客网 时间:2024/06/16 10:31

命令模式的三大角色:

Command:命令接口

Receiver:命令的执行者

Invoker:命令的发送者

以遥控器给电视发送为例进行说明。

1)电视机接口(电视行业总有标准)

package com.cqs.pattern.command;/** * receiver角色:TV接口 * Created by cqs on 10/23/16. */public interface TV {    void turnOn();//开机    void turnOff();//关机    void voiceUp();//音量加大    void voiceDown();//音量减小    void display();//播放某个频道    void channelUp();//上一个频道    void channelDown();//下一个频道}
具体的电视:不同厂家可以有不同的实现

package com.cqs.pattern.command;/** * 具体的receiver类:三星电视 * Created by cqs on 10/23/16. */public class SamsungTV implements TV{    private int channel = 1;    public void turnOn() {        System.out.println("三星电视打开");    }    public void turnOff() {        System.out.println("三星电视关闭");    }    public void voiceUp() {        System.out.println("三星电视音量加1");    }    public void voiceDown() {        System.out.println("三星电视音量减1");    }    public void display() {        System.out.println("三星电视播放频道" + channel);    }    public void channelUp() {        this.channel += 1;    }    public void channelDown() {        this.channel -= 1;    }}

2)命令接口

package com.cqs.pattern.command;/** * 命令接口 * Created by cqs on 10/23/16. */public interface Command {    void execute();}
以及具体的接口命令

package com.cqs.pattern.command;/** * 具体的Command类:开机命令 * Created by cqs on 10/23/16. */public class TurnOnCommand implements Command{    private TV tv;//其实command可以声明为抽象类,将TV属性在抽象类中声明    public TurnOnCommand(TV tv) {        this.tv = tv;    }    public void execute() {        tv.turnOn();    }}

package com.cqs.pattern.command;/** * 具体的Command类:播放频道命令 * Created by cqs on 10/23/16. */public class DisplayCommand implements Command{    private TV tv;//其实command可以声明为抽象类,将TV属性在抽象类中声明    public DisplayCommand(TV tv) {        this.tv = tv;    }    public void execute() {        tv.display();    }}

package com.cqs.pattern.command;/** * 具体的Command类:关机命令 * Created by cqs on 10/23/16. */public class TurnOffCommand implements Command{    private TV tv;    public TurnOffCommand(TV tv) {        this.tv = tv;    }    public void execute() {        tv.turnOff();    }}

3)遥控器(Invoker)
package com.cqs.pattern.command;/** * 遥控器(Invoker角色) * Created by cqs on 10/23/16. */public class RemoteControl {//    protected Command command;////    public void setCommand(Command command) {//        this.command = command;//    }////    public void runCommand(){//        command.execute();//    }    public void runCommand(Command command){        command.execute();    }}
PS:很多例子都是将Invoker按照注释那样实现,个人觉得这样实现的弊端为每次调用的runCommand方法的时候都必须调用setCommand方法,不仅麻烦而且容易出错。

4)测试类

package com.cqs.pattern.command;/** * 测试类 * Created by cqs on 10/23/16. */public class CommandClient {    public static void main(String[] args) {        RemoteControl remoteControl = new RemoteControl();        TV samsungTV = new SamsungTV();        Command turnOnSam = new TurnOnCommand(samsungTV);        remoteControl.runCommand(turnOnSam);        //        Command displaySam = new DisplayCommand(samsungTV);        remoteControl.runCommand(displaySam);        Command turnOffSam = new TurnOffCommand(samsungTV);        remoteControl.runCommand(turnOffSam);    }}
运行结果:



写完了,可以稍微总结下:

1)命令模式其实还是蛮繁琐的,但是其很大的优势就是将命令的发送方(Invoker)与命令的执行方(Receiver)实现了解藕,这通过命令接口(Command)来实现的。这对完全符合开闭原则的:比如需求变了,需要播放Sony电视,或者LG电视,那么只要添加对应的TV实现类,然后高层稍微修改接口对象的就可以使用了。

2)业务才是灵魂,没必要死套模式的标准,比如Command完全可以声明抽象类,减少冗余代码的开发。

最后懒得画UML图了,就找了一张图(若涉及侵权,联系我删除)


0 0