设计模式之——命令设计模式

该模式说白了就是解耦发布者与执行者的依赖关系,新增一个中间调节层,相当于经理的位置,发布者有什么事告诉经理就行了,让后由经理进行管控,选择具体的执行者,发布者和执行者没有直接关联。特别适用于一些大型项目,对象之间频繁通讯的项目,不然维护起来会很复杂。

抽取命令执行接口

package com.zndroid.dm.CommandModel;

/**
 * Created by luzhenyu on 2017/9/13.
 */

/**命令接口,不同接收者均通过这个接口执行具体的命令*/
public interface ICommand {
    void execute();
}
抽取执行者,并添加3个实现吧

package com.zndroid.dm.CommandModel.Receiver;

/**
 * Created by luzhenyu on 2017/9/14.
 */

public abstract class Receiver {
    public abstract void fire();
}
package com.zndroid.dm.CommandModel.Receiver.impl;

import com.zndroid.dm.CommandModel.Receiver.Receiver;

/**
 * Created by luzhenyu on 2017/9/14.
 */

public class HangMu extends Receiver {
    @Override
    public void fire() {
        System.out.println("航母发射  嗖..嗖嗖...");
    }
}
package com.zndroid.dm.CommandModel.Receiver.impl;

import com.zndroid.dm.CommandModel.Receiver.Receiver;

/**
 * Created by luzhenyu on 2017/9/14.
 */

public class HongZhaJi extends Receiver {
    @Override
    public void fire() {
        System.out.println("轰炸机发射  啾..咚咚...");
    }
}
package com.zndroid.dm.CommandModel.Receiver.impl;

import com.zndroid.dm.CommandModel.Receiver.Receiver;

/**
 * Created by luzhenyu on 2017/9/14.
 */

public class TanKe extends Receiver {
    @Override
    public void fire() {
        System.out.println("坦克发射  轰..轰轰...");
    }
}

下面是具体命令的实现:

package com.zndroid.dm.CommandModel.impl;

import com.zndroid.dm.CommandModel.ICommand;
import com.zndroid.dm.CommandModel.Receiver.Receiver;
import com.zndroid.dm.CommandModel.Receiver.impl.HangMu;

/**
 * Created by luzhenyu on 2017/9/13.
 */

/**相当于命令的接收者*/
public class HangMuCommand implements ICommand {
    private Receiver receiver;

    public void setReceiver(Receiver receiver) {
        this.receiver = receiver;
    }

    public HangMuCommand() {
    }

    @Override
    public void execute() {
        if (receiver instanceof HangMu)
            receiver.fire();
    }
}
package com.zndroid.dm.CommandModel.impl;

import com.zndroid.dm.CommandModel.ICommand;
import com.zndroid.dm.CommandModel.Receiver.Receiver;
import com.zndroid.dm.CommandModel.Receiver.impl.HongZhaJi;

/**
 * Created by luzhenyu on 2017/9/13.
 */

/**相当于命令的接收者*/
public class HongZhaJiCommand implements ICommand {
    private Receiver receiver;

    public void setReceiver(Receiver receiver) {
        this.receiver = receiver;
    }
    public HongZhaJiCommand() {
    }

    @Override
    public void execute() {
        if (receiver instanceof HongZhaJi)
            receiver.fire();
    }
}
package com.zndroid.dm.CommandModel.impl;

import com.zndroid.dm.CommandModel.ICommand;
import com.zndroid.dm.CommandModel.Receiver.Receiver;
import com.zndroid.dm.CommandModel.Receiver.impl.TanKe;

/**
 * Created by luzhenyu on 2017/9/13.
 */

/**相当于命令的接收者*/
public class TanKeCommand implements ICommand {
    private Receiver receiver;
    public void setReceiver(Receiver receiver) {
        this.receiver = receiver;
    }

    public TanKeCommand() {
    }

    @Override
    public void execute() {
        if (receiver instanceof TanKe)
            receiver.fire();
    }
}

关键在于中间管理者,他可以管控命令的增减、日志记录、撤销等
package com.zndroid.dm.CommandModel;

import com.zndroid.dm.CommandModel.Receiver.Receiver;
import com.zndroid.dm.CommandModel.Receiver.impl.HangMu;
import com.zndroid.dm.CommandModel.Receiver.impl.HongZhaJi;
import com.zndroid.dm.CommandModel.Receiver.impl.TanKe;
import com.zndroid.dm.CommandModel.impl.HangMuCommand;
import com.zndroid.dm.CommandModel.impl.HongZhaJiCommand;
import com.zndroid.dm.CommandModel.impl.TanKeCommand;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by luzhenyu on 2017/9/13.
 */

/**命令的中间调节者 除了可以下达命令之外,其实还可以撤销命令,存储命令日志等等*/
public class GeneralManager {

    private List<Receiver> receivers;//可以选择的接收者
    private List<ICommand> commands;//命令集

    public GeneralManager() {
        commands = new ArrayList<>();
        receivers = new ArrayList<>();
    }

    public void order() {
        for (ICommand command :
                commands) {
            command.execute();
        }

        commands.clear();//命令执行完后回收
    }

    public Receiver chooseReceiver(ICommand c) {
        if (c instanceof HangMuCommand)
            return new HangMu();
        if (c instanceof HongZhaJiCommand)
            return new HongZhaJi();
        if (c instanceof TanKeCommand)
            return new TanKe();
        return null;
    }

    public void receiverCommand(ICommand command) {
        commands.add(command);
    }
}

使用如下:

/**
         * 命令模式
         * 命令模式专注于提供一个调解人介于需要交流的对象之间来帮助完成对象间的松耦合,
         * 请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
         * 说白了就是将发起者和执行者解耦分离,由中间层管理和调控,这个中间层就相当于部门经理,负责调控需求发起者和执行者之间的关系,减少发起者与执行者太过依赖的关系
         * 优点:
         * 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
         * 缺点:
         * 使用命令模式可能会导致某些系统有过多的具体命令类。
         *
         * java.util.Timer类中scheduleXXX()方法
         * java Concurrency Executor execute() 方法
         * java.lang.reflect.Method invoke()方法
         * */
        //《战狼II》票房已经突破56亿啦,真是很喜欢这部电影,是一部良心之作,里面最触动我的是那一声 -- “开火”
        //吴京作为客户端提出火力增援的请求,中间层便是丁海峰一类的将军、司令一类,具体的执行者便是航母、坦克之类的,这就是活生生的命令模式
        //如果吴京可以直接控制航母、坦克,那么,有可能会引起国际争端,多亏吴京是好人,要是坏人能够直接控制,那还了得,弗兰克·格里罗不就是如此吗
        GeneralManager manager = new GeneralManager();
        WuJingClient client = new WuJingClient(manager);//吴京联系长官

        HangMuCommand command = new HangMuCommand();
        command.setReceiver(manager.chooseReceiver(command));//请求类型,并由长官选择合适的执行者
        client.requestCommand(command);//吴京发起请求

        HongZhaJiCommand command1 = new HongZhaJiCommand();
        command1.setReceiver(manager.chooseReceiver(command1));
        client.requestCommand(command1);

        TanKeCommand command2 = new TanKeCommand();
        command2.setReceiver(manager.chooseReceiver(command2));
        client.requestCommand(command2);
        //好吧,吴京发起了3个火力增援的请求

        manager.order();//舰长一声令下 -- “开火”,厉害了我的国

        log("--------------------------------------------------");
        WuJingClient client1 = new WuJingClient(manager);//另外一个吴京
        TanKeCommand tanKeCommand = new TanKeCommand();
        tanKeCommand.setReceiver(manager.chooseReceiver(tanKeCommand));
        client1.requestCommand(tanKeCommand);

        manager.order();//舰长根据不同的客户需求执行相对应的命令

        log("----------------我是分割线-----------------");

执行结果:
[ ======================================== ]
航母发射 嗖..嗖嗖...
轰炸机发射 啾..咚咚...
坦克发射 轰..轰轰...
[ -------------------------------------------------- ]
坦克发射 轰..轰轰...
[ ----------------我是分割线----------------- ]
[ ======================================== ]



【欢迎上码】

【微信公众号搜索 h2o2s2】


猜你喜欢

转载自blog.csdn.net/luzhenyuxfcy/article/details/77988451