java设计模式之命令

命令模式将请求封装成一系列对象,对象里包含指令和数据。

在分布式架构中,master需要给worker分发任务,worker完成后需要把任务处理结果返回给master。

master/worker之间的信息交互会有很多不同的指令和数据,这种不同消息的实现就可以采用命令模式。

我们首先定义一个命令对象

一、命令模式同步实现

public class Command implements Serializable,Cloneable {
    private static AtomicLong idGenerator=new AtomicLong(1L);
    private Long id;
    private String request;
    private String response;

    public Command( String content) {
        this.id = idGenerator.getAndIncrement();
        this.request = content;
    }

    public String getResponse() {
        return response;
    }

    public void setResponse(String response) {
        this.response = response;
    }

    protected Command clone()  {
        try {
            return (Command) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Command{" +
                "id=" + id +
                ", request='" + request + '\'' +
                ", response='" + response + '\'' +
                '}';
    }
}

然后定义一个master,master负责向worker发送命令

public class Master {
    void dispatch(Worker worker,Command command){
        System.out.println("dispatch a command:"+command +"to "+worker.getClass().getSimpleName());
        Command response = worker.process(command);
        System.out.println("receive a command"+response);
    }

    public static void main(String[] args) {
        Command command1 = new Command("hello,python!");
        Command command2 = new Command("hello,java!");
        Master master = new Master();
        Worker worker1 = new Worker1();
        Worker worker2 = new Worker2();
        master.dispatch(worker1,command1);
        master.dispatch(worker2,command2);
    }
}

定义一个worker接口,用于处理命令,并返回任务的结果

public interface Worker {
    Command process(Command command);
}

public class Worker1 implements Worker {
    @Override
    public Command process(Command command) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Command clone = command.clone();
        clone.setResponse("worker1  ok");
        return clone;
    }
}

public class Worker2 implements Worker {
    @Override
    public Command process(Command command) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Command clone = command.clone();
        clone.setResponse("worker2  ok");
        return clone;
    }
}

执行master,输出:

dispatch a command:Command{id=1, request='hello,python!', response='null'}to Worker1
receive a commandCommand{id=1, request='hello,python!', response='worker1  ok'}
dispatch a command:Command{id=2, request='hello,java!', response='null'}to Worker2
receive a commandCommand{id=2, request='hello,java!', response='worker2  ok'}

 二、命令模式异步实现

其实分布式系统中,更常见的实现是异步io,我们给Worker接口添加一个异步处理方法

public interface Worker {
    /**
     * 同步处理
     * @param command
     * @return
     */
    Command process(Command command);

    /**
     * 异步处理
     * @param command
     */
    void asyncProcess(Command command);
}

定义一个实现了Worker接口的实现类

public class AsyncWorker implements Worker {
    @Override
    public Command process(Command command) {
        return null;
    }

    @Override
    public void asyncProcess(Command command){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Command clone = command.clone();
        Long id = clone.getId();
        clone.setResponse("AsyncWorker ok");
        ResponseFuture future = ResponseFuture.getFuture(id);
        future.putResponse(clone);
    }
}

因为是异步处理,我们定义一个Future类

/**
 * 任务结果future类
 */
public class ResponseFuture {
    private static final Map<Long,ResponseFuture> futures=new ConcurrentHashMap<>(256);
    private long requestId;
    private CountDownLatch latch=new CountDownLatch(1);
    private Command response;
    private final InvokeCallback invokeCallback;

    public ResponseFuture(long requestId,  InvokeCallback invokeCallback) {
        this.requestId = requestId;
        this.invokeCallback = invokeCallback;
        futures.put(requestId, this);
    }

    public void executeInvokeCallback() {
        if (invokeCallback != null) {
            invokeCallback.operationComplete(this);
        }
    }

    public void putResponse(final Command responseCommand) {
        this.response = responseCommand;
        this.latch.countDown();
        futures.remove(requestId);
    }

    public Command getResponseCommand() {
        return response;
    }

    public static ResponseFuture getFuture(long requestId) {
        return futures.get(requestId);
    }
}

定义一个回调接口,用于获得结果后的回调

/**
 * 回调接口
 */
public interface InvokeCallback {
    void operationComplete(final ResponseFuture responseFuture);
}

因为需要异步获取结果,我们对command类进行了扩展

public class Command implements Serializable,Cloneable {
    private static AtomicLong idGenerator=new AtomicLong(1L);
    private Long id;
    private String request;
    private String response;

    public Command( String content) {
        this.id = idGenerator.getAndIncrement();
        this.request = content;
    }

    public Long getId() {
        return id;
    }

    public String getResponse() {
        return response;
    }

    public void setResponse(String response) {
        this.response = response;
    }

    protected Command clone()  {
        try {
            return (Command) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Command{" +
                "id=" + id +
                ", request='" + request + '\'' +
                ", response='" + response + '\'' +
                '}';
    }
}

master发生异步请求

public class Master {
//    void dispatch(Worker worker, Command command) {
//        System.out.println("dispatch a command:" + command + "to " + worker.getClass().getSimpleName());
//        Command response = worker.process(command);
//        System.out.println("receive a command" + response);
//    }

    void dispatchAsync(Worker worker, Command command, final InvokeCallback invokeCallback) {
        System.out.println("dispatch a command:" + command + "to " + worker.getClass().getSimpleName());
        Long requestId = command.getId();
        ResponseFuture responseFuture = new ResponseFuture(requestId, invokeCallback);
        worker.asyncProcess(command);
        responseFuture.executeInvokeCallback();


    }

    public static void main(String[] args) {
        Master master = new Master();
//        Command command1 = new Command("hello,sync!");
//        Worker worker1 = new SyncWorker();
//        System.out.println("dispatch Sync");
//        master.dispatch(worker1, command1);
        Command command2 = new Command("hello,async!");
        Worker worker2 = new AsyncWorker();
        System.out.println("dispatch ASync");
        master.dispatchAsync(worker2, command2, new InvokeCallback() {
            @Override
            public void operationComplete(ResponseFuture responseFuture) {
                Command responseCommand = responseFuture.getResponseCommand();
                System.out.println(responseCommand);
            }
        });
    }
}

 

输出:

dispatch ASync
dispatch a command:Command{id=1, request='hello,async!', response='null'}to AsyncWorker
Command{id=1, request='hello,async!', response='AsyncWorker ok'}

上面的实现是分布式架构的一种简化,以方便在单机进行演示。

实际的分布式架构中,master拿不到worker对象,worker也不可能拿到Future对象,异步消息的传递一般是基于异步io框架(比如netty)的channel来实现的。

netty不是我们本文讨论的重点,这里就不做更多的描述了。

 

posted @ 2022-01-25 13:48  Mars.wang  阅读(54)  评论(0编辑  收藏  举报