Command设计模式

命令模式的三大角色:

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值