Java设计模式--命令模式

命令模式

以网上很多人的例子:点餐。

以前吃烧烤,每一个客人都是直接跟烧烤师傅说吃什么,烧烤师傅【又要烧烤又要记住每个客人点了什么】记性差。这里是行为请求者和行为实现者的紧耦合,不好。

现在呢,每个烧烤摊有个服务员,客人想吃啥,直接跟服务员说,服务员把每一份订单给烧烤师傅看,烧烤师傅【只需要根据单子烧烤】效率提升。这里是行为请求者和行为实现者的解耦,好。

大概过程如图:

 

角色:

客户角色(Client):创造了一个具体命令(ConcreteCommand)并确定其接收者。

命令角色(Command):所有具体命令类的抽象接口。

具体命令角色(ConcreteCommand):定义一个接收者(Receiver)和行为之间的弱耦合;实现execute方法,调用接收者(Receiver)的相关操作。

请求者角色(Invoker):负责调用命令对象(Command)执行请求,相关的方法叫做行动方法。

接收者角色(Receiver):具体实施和执行一个请求。

UML图:

示例:

Command

/**
 * 命令接口
 */

public interface Command {

    void execute();
}

Receiver

/**
 * 命令接收者
 */
public class Receiver {
    public Receiver() {
    }
    public void action(){
        // 命令真正执行的逻辑
        System.out.println("~~~~~~~~~~~~~");
    }
}

ConcreteCommand

/**
 * 命令接口实现类
 */
public class ConcreteCommand implements Command {
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    public void execute() {
        receiver.action();
    }
}

Invoker

/**
 * 命令调用者
 */
public class Invoker {

    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void action(){
        command.execute();
    }
}

Client

/**
 *  命令 + 实现类
 *  命令调用者
 *  命令接收者
 *  客户端
 *
 *  客户端发出命令,由命令调用者负责传递,最终命令接收者执行。客户端不与命令细节直接接触。
 */
public class Client {
    public static void main(String[] args){
        Receiver receiver = new Receiver();
        Command command = new ConcreteCommand(receiver);
        Invoker invoker = new Invoker(command);
        invoker.action();
    }
}

命令模式有什么好处

实现了命令请求和命令实现的解耦合(中间加了个调用者),说白了,就是让命令实现专注自己职责内的事情,不需要管其他的。

不好的地方就是Command实现类可能会有N个。

实例

来自《Java与模式》中茱莉亚玩收音机的例子。说茱莉亚(客户端)玩收音机,只需要手按相关的按键(命令调用者)即可,不需要关心收音机(命令实现者)播放或者停止的细节。

 

代码:

Command

public interface Command {

    void execute();
}

AutoPlayer

/**
 * 命令实现细节
 */
public class AutoPlayer {

    public void play(){
        System.out.println("Play Music");
    }

    public void stop(){
        System.out.println("Stop Music");
    }
}

具体命令:Play

/**
 * 播放命令
 */
public class PlayCommand implements Command {

    private AutoPlayer autoPlayer;

    public PlayCommand(AutoPlayer autoPlayer) {
        this.autoPlayer = autoPlayer;
    }

    public void execute() {
        autoPlayer.play();
    }
}

具体命令:Stop

/**
 * 停止命令
 */
public class StopCommand implements Command {

    private AutoPlayer autoPlayer;

    public StopCommand(AutoPlayer autoPlayer) {
        this.autoPlayer = autoPlayer;
    }

    public void execute() {
        autoPlayer.stop();
    }
}

命令调用者:Keyboard

/**
 * 命令调用者
 */
public class KeyBoard {

    private Command playCommand;
    private Command stopCommand;

    public KeyBoard(Command playCommand, Command stopCommand) {
        this.playCommand = playCommand;
        this.stopCommand = stopCommand;
    }

    public void play(){
        playCommand.execute();
    }

    public void stop(){
        stopCommand.execute();
    }
}

客户端:Julia

public class Julia {

    public static void main(String[] args){
        AutoPlayer player = new AutoPlayer();
        PlayCommand playCommand = new PlayCommand(player);
        StopCommand stopCommand = new StopCommand(player);
        KeyBoard keyBoard = new KeyBoard(playCommand, stopCommand);
        keyBoard.play();
        keyBoard.stop();
    }

}

回调函数

代码

Callback

/**
 * 回调接口(命令接口)
 */
public interface Callback {

    void callback();
}

商店

/**
 * 命令调用者(商店店员)
 */
public class SomeService {

    private Callback callback;
    private String phone;

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public void service(){
        System.out.println("来货了,给客人【"+ phone +"】打电话......");
        callback.callback();
    }
}

客人

public class Client {

    public static void main(String[] args){

        SomeService service = new SomeService();
        service.setPhone("12306");
        service.setCallback(() -> {
            // 这里的角色是具体的命令实现
            System.out.println("货到了,我来取!");
        });
        service.service();
    }
}

结果:

 

posted @ 2020-08-31 14:56  露娜妹  阅读(189)  评论(0编辑  收藏  举报