文章
问答
冒泡
流程引擎系列之设计模式
【工欲善其事,必先利其器】
在activiti、flowable、camunda等开源流程引擎框架的设计中, 除了实现的程序语言外,尤为重要的是设计模式,而命令模式和责任链模式则是其中的精髓所在。
 

命令模式(Command Pattern):

分类:行为型模式
介绍:请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被重复多次、取消、Undo和Redo。
 
Structure:
 
场景:
  1. Java GUI编程中任一按钮都是一条命令。
  2. 业务操作解耦,服务的Invoker和Receiver不进行直接交互,两者可以独立开发互不影响。
  3. 工作队列
  4. 日志请求
  5. 线程池
  6. 事务系统
  7. JDK中的命令模式
java.util.Timer类中scheduleXXX()方法
java Concurrency Executor execute() 方法
java.lang.reflect.Method invoke()方法
 
优点:
  1. 降低系统的耦合度,服务的请求方和接口方解耦
  2. 扩展性良好,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,且满足“开闭原则”。
  3. 可以实现宏命令。命令模式结合组合模式,可以将多个命令装配成一个组合命令,即宏命令。
  4. 方便实现 Undo 和 Redo 操作。
  5. 有一定的扩展性,可以在现有命令的基础上,增加额外功能。比如日志记录,结合装饰器模式会更加灵活。
 
缺点:
  1. 当为每个具体操作都实现一个具体命令类时,就会产生过多的命令类,从而增加系统的复杂性。
  2. 程序以命令模式进行架构、解耦请求和实现时,会引入额外的抽象接口和请求对象,这样就增加了解读代码的困难度。但在使用设计模式时,都不可避免的会遇到此类问题,抽象必然会新增额外类的数量,
  3. 代码的解耦也肯定比聚合更不易理解。
 
Code Script:
/**
 * 调解人接口
 * 用于如何定义具体的调解人
 */
public interface ChatMediator {
    void sendMessage(String msg, User user);

    void addUser(User user);

}


/**
 * 用户接口
 * 用户可以发送接送信息,因此应该有用户接口或者抽象类
 */
public abstract class User {
    protected ChatMediator mediator;
    protected String name;

    public User(ChatMediator med, String name) {
        this.mediator = med;
        this.name = name;
    }

    public abstract void send(String msg);

    public abstract void receive(String msg);

}


/**
 * 调解人实体类
 * 包含了再组群中的一些类用户并且提供用户之间如何交流的逻辑
 */
public class ChatMediatorImpl implements ChatMediator {
    private List<User> users;

    public ChatMediatorImpl() {
        this.users = new ArrayList<>();
    }

    @Override
    public void addUser(User user) {
        this.users.add(user);
    }

    @Override
    public void sendMessage(String msg, User user) {
        for (User u : this.users) {
            //message should not be received by the user sending it
            if (u != user) {
                u.receive(msg);
            }
        }
    }
}


/**
 * 用户的实体类
 */
public class UserImpl extends User {

    public UserImpl(ChatMediator med, String name) {
        super(med, name);
    }

    @Override
    public void send(String msg) {
        System.out.println(this.name + ": Sending Message=" + msg);
        mediator.sendMessage(msg, this);
    }

    @Override
    public void receive(String msg) {
        System.out.println(this.name + ": Received Message:" + msg);
    }

}


/**
 * 命令模式客户端
 */
public class ChatClient {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatMediatorImpl();
        User user1 = new UserImpl(mediator, "ZhangSan");
        User user2 = new UserImpl(mediator, "LiSi");
        User user3 = new UserImpl(mediator, "WangWu");
        User user4 = new UserImpl(mediator, "ZhaoLiu");
        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);
        mediator.addUser(user4);

        user1.send("Hi Man");
    }
}

//Output print:
ZhangSan: Sending Message=Hi Man
LiSi: Received Message:Hi Man
WangWu: Received Message:Hi Man
ZhaoLiu: Received Message:Hi Man
 

责任链模式(Chain of Responsibility Pattern):

分类:行为型模式
介绍:为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。
责任链模式在结构上几乎与装饰器模式相同,不同之处在于,对于装饰器,所有类都处理请求,而对于责任链,链中恰好​​有一个类处理请求。
 
Structure:
 
场景:
  1. 当一个请求可以被多个对象处理时,由运行时自动确定哪个对象来处理该请求
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
  3. 一组对象处理请求可以被动态指定时
 
优点:
  1. 降低耦合度。可以使请求的发送者和接收者解耦。
  2. 简化对象。在使用责任链模式中可以使得对象不需要知道链的结构。
  3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  4. 扩展方便,比较容易的增加新的请求处理类。
 
缺点:
  1. 请求被接收的有效性不能保证,可能会出现不被接口方接收到的情况。
  2. 可能会降低系统性能,在调试代码时也不太方便,甚至在有的情况下出现循环调用。
  3. 不易于排查问题,运行时的特征不容易被观察到。
 
Code Script:
/**
 * 抽象处理者
 */
public abstract class Handler {
    //下一个责任链成员
    protected Handler nextHandler;

    public Handler getNextHandler() {
        return nextHandler;
    }

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 处理传递过来的时间
    public abstract void handleMessage(int type);
}


public class FirstHandler extends Handler {
    @Override
    public void handleMessage(int type) {
        if (type == 1 || type == 3) {
            System.out.println("FirstHandler解决了问题!");
        } else {
            System.out.println("FirstHandler解决不了问题???");
            if (nextHandler != null) {
                nextHandler.handleMessage(type);
            } else {
                System.out.println("没有人能处理这个消息");
            }
        }
    }
}

public class SecondHandler extends Handler {
    @Override
    public void handleMessage(int type) {
        if (type == 2 || type == 5) {
            System.out.println("SecondHandler解决了问题!");
        } else {
            System.out.println("SecondHandler解决不了问题???");
            if (nextHandler != null) {
                nextHandler.handleMessage(type);
            } else {
                System.out.println("没有人能处理这个消息");
            }
        }
    }
}

public class ThirdHandler extends Handler {
    @Override
    public void handleMessage(int type) {
        if (type == 4 || type == 6) {
            System.out.println("ThirdHandler解决了问题!");
        } else {
            System.out.println("ThirdHandler解决不了问题???");
            if (nextHandler != null) {
                nextHandler.handleMessage(type);
            } else {
                System.out.println("没有人能处理这个消息");
            }
        }
    }
}

public class Client {
    public static void main(String[] args) {
        // 初始化责任链:handler1 -> handler2 -> handler3
        Handler handler1 = new FirstHandler();
        Handler handler2 = new SecondHandler();
        Handler handler3 = new ThirdHandler();
        handler2.setNextHandler(handler3);
        handler1.setNextHandler(handler2);
        // 处理事件
        System.out.println("--------------Message1");
        handler1.handleMessage(1);
        System.out.println("--------------Message2");
        handler1.handleMessage(2);
        System.out.println("--------------Message3");
        handler1.handleMessage(4);
        System.out.println("--------------Message4");
        handler1.handleMessage(7);
    }
}


//Output print:
--------------Message1
FirstHandler解决了问题!
--------------Message2
FirstHandler解决不了问题???
SecondHandler解决了问题!
--------------Message3
FirstHandler解决不了问题???
SecondHandler解决不了问题???
ThirdHandler解决了问题!
--------------Message4
FirstHandler解决不了问题???
SecondHandler解决不了问题???
ThirdHandler解决不了问题???
没有人能处理这个消息
 
 
参考链接:
 
 


关于作者

Miraclewcg
上善若水
获得点赞
文章被阅读