# 行为型模式

作者:Ethan.Yang
博客:https://blog.ethanyang.cn (opens new window)
相关代码参考: 设计模式代码仓库 (opens new window)


# 委派模式

允许对象组合实现与继承相同的代码重用, 基本作用是负责任务的调用和分配

# 模式定义与角色

  1. 抽象任务角色: 定义一个抽象接口, 有若干实现类
  2. 委派者角色: 负责在各个具体角色实例之间做出决策, 并判断并调用具体实现的方法
  3. 具体任务角色: 真正执行任务的角色

# 委派模式的实现

  1. 抽象任务角色

    public interface Employee {
    
        void doTask(String task);
    }
    
    1
    2
    3
    4
  2. 具体任务角色

    public class EmployeeA implements Employee {
    
        @Override
        public void doTask(String task) {
            System.out.println("员工A 负责处理:" + task);
        }
    }
    
    
    public class EmployeeB implements Employee {
    
        @Override
        public void doTask(String task) {
            System.out.println("员工B 负责处理:" + task);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  3. 委派者角色

    public class Leader implements Employee {
    
        private Map<String, Employee> employeeMap = new HashMap<>();
    
        public Leader() {
            employeeMap.put("开发", new EmployeeA());
            employeeMap.put("测试", new EmployeeB());
        }
    
        @Override
        public void doTask(String task) {
            if (!employeeMap.containsKey(task)) {
                System.out.println("Leader:暂无员工可处理该任务:" + task);
                return;
            }
            employeeMap.get(task).doTask(task);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
  4. 发任务

    public class Boss {
    
        public void command(String task, Leader leader) {
            leader.doTask(task);
        }
    }
    
    1
    2
    3
    4
    5
    6
  5. 测试

    public class Test {
    
        public static void main(String[] args) {
            Boss boss = new Boss();
            Leader leader = new Leader();
            boss.command("开发", leader);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

# 模板方法模式

定义一个操作中的算法框架, 将一些步骤延迟到子类, 使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。

# 模式定义与角色

  1. 抽象模板: 定义了一套算法框架/流程
  2. 具体实现: 对算法框架/流程的某些步骤进行了实现
  3. 钩子方法: 可选的扩展点, 子类自行决定是否重写

# 模板方法的实现

  1. 抽象模板

    public abstract class AbstractApprovalProcess {
    
        // 模板方法,审批流程固定不可变
        public final void approve() {
            System.out.println("开始审批流程:");
    
            fillForm();
            submitToSystem();
    
            if (needManagerApproval()) { // 钩子方法
                managerApprove();
            }
    
            financeApprove();
            archive();
        }
    
        // 步骤1:填写申请表
        protected abstract void fillForm();
    
        // 步骤2:提交系统
        private void submitToSystem() {
            System.out.println("提交审批系统");
        }
    
        // 步骤3:部门经理审批(可选)
        protected void managerApprove() {
            System.out.println("部门经理审批通过");
        }
    
        // 步骤4:财务审批
        private void financeApprove() {
            System.out.println("财务审批通过");
        }
    
        // 步骤5:归档
        private void archive() {
            System.out.println("流程归档");
        }
    
        // 钩子方法:子类决定是否需要经理审批
        protected boolean needManagerApproval() {
            return true;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
  2. 具体实现

    public class LeaveApproval extends AbstractApprovalProcess {
    
        @Override
        protected void fillForm() {
            System.out.println("填写请假申请表");
        }
    
        @Override
        protected boolean needManagerApproval() {
            // 请假不需要申请审批
            return false;
        }
    }
    
    public class ReimbursementApproval extends AbstractApprovalProcess {
    
        @Override
        protected void fillForm() {
            System.out.println("填写报销申请表");
        }
    
        // 默认需要经理审批,不重写 needManagerApproval()
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
  3. 测试

    public class Test {
    
        public static void main(String[] args) {
            System.out.println("== 请假流程 ==");
            AbstractApprovalProcess leave = new LeaveApproval();
            leave.approve();
    
            System.out.println("\n== 报销流程 ==");
            AbstractApprovalProcess reimbursement = new ReimbursementApproval();
            reimbursement.approve();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

# 策略模式

将定义的算法家族分别封装, 让他们之间可以互相替换, 从而实现同一行为在不同场景下具备不同实现

# 模式定义与角色

  1. 抽象策略角色: 规定策略或算法的行为
  2. 具体策略角色: 具体的策略或算法实现
  3. 上下文角色: 用来操作策略的上下文环境, 屏蔽高层模块对策略的直接访问

# 策略模式的实现

  1. 抽象策略角色

    public interface PayStrategy {
    
        void pay(double amount);
    }
    
    1
    2
    3
    4
  2. 具体策略角色

    public class AliPayStrategy implements PayStrategy {
        @Override
        public void pay(double amount) {
            System.out.println("使用支付宝支付:" + amount + " 元");
        }
    }
    
    public class BankPayStrategy implements PayStrategy {
        @Override
        public void pay(double amount) {
            System.out.println("使用银行卡支付:" + amount + " 元");
        }
    }
    
    public class WeChatPayStrategy implements PayStrategy {
        @Override
        public void pay(double amount) {
            System.out.println("使用微信支付:" + amount + " 元");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  3. 策略上下文

    public interface PayStrategy {
    
        void pay(double amount);
    }
    
    1
    2
    3
    4
  4. 测试

    public class Test {
    
        public static void main(String[] args) {
            double amount = 199.99;
            PayContext payContext = new PayContext(new AliPayStrategy());
            payContext.executePayment(amount);
    
            PayContext payContext1 = new PayContext(new BankPayStrategy());
            payContext1.executePayment(amount);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

# 责任链模式

将链中的每一个节点看做一个对象, 每个节点处理的请求均不同, 且内部自动维护一个下一节点对象。当一个请求从链的首端发出, 会沿着链的路径依次传递给每一个节点对象, 直至有对象处理这个请求为止。

# 模式定义与角色

  1. 抽象处理者: 定义一个请求处理的方法, 并维护一个下一个处理节点Handler对象的引用。
  2. 具体处理者: 对请求进行处理, 如果不感兴趣则进行转发。

# 责任链模式的实现

看一个登录校验案例

@Data
public class Member {

    private String loginName;
    private String loginPass;
    private String roleName;

    public Member(String loginName, String loginPass, String roleName) {
        this.loginName = loginName;
        this.loginPass = loginPass;
        this.roleName = roleName;
    }


    public Member(String loginName, String loginPass) {
        this.loginName = loginName;
        this.loginPass = loginPass;
    }
}

public class MemberService {

    public void login(String loginName, String loginPass) {

        if (StringUtils.isEmpty(loginName) ||
                StringUtils.isEmpty(loginPass)) {
            System.out.println("用户名或密码为空");
        }
        System.out.println("用户名和密码校验成功,可以往下执行");

        Member member = checkExists(loginName, loginPass);
        if (null == member) {
            System.out.println("用户不存在");
            return;
        }
        System.out.println("登录成功!");
        member.setRoleName("管理员");


        if(!"管理员".equals (member.getRoleName())) {
            System.out.println("您不是管理员,没有操作权限");
            return;
        }
        System.out.println("允许操作");
    }

    private Member checkExists(String loginName, String loginPass) {
        Member member = new Member(loginName, loginPass);
        return member;
    }

    public static void main(String[] args) {
        MemberService memberService = new MemberService();
        memberService.login("yym", "123");
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

用责任链模式改造:

  1. 抽象处理者

    public abstract class Handler<T> {
    
        /**
         * 每一个处理器都持有下一个处理器的引用
         */
        protected Handler chain;
        public void next(Handler handler) {
            this.chain = handler;
        }
    
        public abstract void doHandler(Member member);
    
        // 用构造者模式进行改装
        public static class Builder<T> {
            private Handler<T> head;
            private Handler<T> tail;
    
            public Builder<T> addHandler(Handler<T> handler) {
                if (this.head == null) {
                    this.head = this.tail = handler;
                    return this;
                }
                this.tail.next(handler);
                this.tail = handler;
                return this;
            }
    
            public Handler<T> build() {
                return this.head;
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
  2. 具体处理者

    public class ValidateHandler extends Handler {
    
        @Override
        public void doHandler(Member member) {
            if (StringUtils.isEmpty(member.getLoginName()) ||
                    StringUtils.isEmpty(member.getLoginPass())) {
                System.out.println("用户名或密码为空");
            }
            System.out.println("用户名和密码校验成功,可以往下执行");
            this.doHandler(member);
        }
    }
    
    public class LoginHandler extends Handler {
        @Override
        public void doHandler(Member member) {
    
            if (null == member) {
                System.out.println("用户不存在");
                return;
            }
            System.out.println("登录成功!");
            member.setRoleName("管理员");
    
            this.doHandler(member);
        }
    }
    
    public class AuthHandler extends Handler {
    
        @Override
        public void doHandler(Member member) {
            if(!"管理员".equals (member.getRoleName())) {
                System.out.println("您不是管理员,没有操作权限");
                return;
            }
            System.out.println("允许操作");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
  3. 改造原有流程

    public class MemberService {
    
        public void login(String loginName, String loginPass) {
    
            Handler.Builder builder = new Handler.Builder();
            builder.addHandler(new ValidateHandler())
                    .addHandler(new LoginHandler())
                    .addHandler(new AuthHandler());
    
            builder.build().doHandler(new Member(loginName, loginPass));
        }
    
        public static void main(String[] args) {
            MemberService memberService = new MemberService();
            memberService.login("yym", "123");
        }
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

# 迭代器模式

提供一种顺序访问集合/容器对象元素的方法, 无须暴露集合内部表示, 为不同的集合提供一致的遍历行为, 不用关心容器内部元素的组成结构。

# 模式定义与角色

  1. 抽象迭代器: 抽象迭代器负责定义访问和遍历元素的接口
  2. 具体迭代器: 提供具体的元素遍历行为
  3. 抽象容器: 负责定义提供具体迭代器的接口
  4. 具体容器: 创建具体迭代器

# 迭代器模式的实现

  1. 抽象迭代器

    public interface Iterator<E> {
    
        boolean hasNext();
        E next();
    }
    
    1
    2
    3
    4
    5
  2. 抽象容器

    public interface Aggregate<E> {
    
        Iterator<E> createIterator();
    }
    
    1
    2
    3
    4
  3. 具体迭代器

    public class ConcreteIterator<E> implements Iterator<E> {
    
        private ConcreteAggregate<E> aggregate;
        private int index = 0;
    
        public ConcreteIterator(ConcreteAggregate<E> aggregate) {
            this.aggregate = aggregate;
        }
    
        @Override
        public boolean hasNext() {
            return index < aggregate.size();
        }
    
        @Override
        public E next() {
            return aggregate.get(index++);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  4. 具体容器

    public class ConcreteAggregate <E> implements Aggregate<E>{
    
        private List<E> items = new ArrayList<>();
    
        public void add(E item) {
            items.add(item);
        }
    
        public E get(int index) {
            return items.get(index);
        }
    
        public int size() {
            return items.size();
        }
    
        @Override
        public Iterator<E> createIterator() {
            return new ConcreteIterator<>(this);
        }
    
        public static void main(String[] args) {
            ConcreteAggregate<String> names = new ConcreteAggregate<>();
            names.add("Alice");
            names.add("Bob");
            names.add("Charlie");
    
            Iterator<String> iterator = names.createIterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

# 命令模式

命令模式是一种行为型设计模式,将“请求”封装成对象,使我们可用不同的请求、队列或日志参数化其他对象,同时支持撤销操作。

# 模式定义

  • 命令(Command):抽象命令,声明执行操作的接口。
  • 具体命令(ConcreteCommand):实现命令接口,绑定接收者并调用相应操作。
  • 接收者(Receiver):真正执行命令的对象。
  • 调用者(Invoker):请求者,持有命令对象并触发命令。
  • 客户端(Client):创建命令对象并设置调用者和接收者之间的关系。

# 示例代码

  1. 命令

    public interface Command {
    
        void execute();
    }
    
    1
    2
    3
    4
  2. 接收者

    public class Light {
    
        public void turnOn() {
            System.out.println("灯已打开");
        }
    
        public void turnOff() {
            System.out.println("灯已关闭");
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  3. 具体命令

    public class LightOffCommand implements Command {
    
        private Light light;
        public LightOffCommand(Light light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            light.turnOff();
        }
    }
    
    public class LightOnCommand implements Command {
    
        private Light light;
        public LightOnCommand(Light light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            light.turnOn();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  4. 调用者

    public class RemoteControl {
    
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void pressButton() {
            command.execute();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  5. 测试

    public class Test {
    
        public static void main(String[] args) {
            Light light = new Light();
    
            Command lightOn = new LightOnCommand(light);
            Command lightOff = new LightOffCommand(light);
    
            RemoteControl remote = new RemoteControl();
    
            remote.setCommand(lightOn);
            remote.pressButton(); // 输出:灯已打开
    
            remote.setCommand(lightOff);
            remote.pressButton(); // 输出:灯已关闭
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

# 状态模式

状态模式是一种行为型设计模式,允许对象在内部状态改变时改变它的行为,使其看起来就像修改了它的类一样。

# 模式定义

  • Context(上下文):持有当前状态对象,并对外提供状态切换与行为调用接口。
  • State(抽象状态):定义所有具体状态的通用接口。
  • ConcreteState(具体状态):实现具体状态下的行为逻辑,并可切换至其他状态。

# 示例代码

  1. Context

    public class Context {
    
        private State state;
    
        public void setState(State state) {
            this.state = state;
        }
    
        public State getState() {
            return state;
        }
    
        public void request() {
            if (state != null) {
                state.handle(this);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
  2. 状态接口

    public interface State {
        void handle(Context context);
    }
    
    1
    2
    3
  3. 具体状态

    public class StartState implements State {
    
        @Override
        public void handle(Context context) {
            System.out.println("播放器处于开始状态");
            context.setState(this);
        }
    
        @Override
        public String toString() {
            return "开始状态";
        }
    }
    
    public class StopState implements State {
    
        @Override
        public void handle(Context context) {
            System.out.println("播放器处于停止状态");
            context.setState(this);
        }
    
        @Override
        public String toString() {
            return "停止状态";
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
  4. 测试

    public class Test {
    
        public static void main(String[] args) {
            Context context = new Context();
    
            State start = new StartState();
            start.handle(context);
            System.out.println("当前状态:" + context.getState());
    
            State stop = new StopState();
            stop.handle(context);
            System.out.println("当前状态:" + context.getState());
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

# 备忘模式

备忘模式(Memento Pattern)用于在不破坏封装性的情况下,保存一个对象的内部状态,以便在未来需要时可以恢复到该状态。在软件中,常常需要实现“撤销”或“回滚”功能,而备忘模式通过保存对象的状态快照,实现状态的保存与恢复。

# 模式定义

  • 发起人(Originator):负责创建备忘录并存储自身状态,也可通过备忘录恢复状态。
  • 备忘录(Memento):存储发起人的内部状态,保护封装,不允许外部访问其内容。
  • 管理者(Caretaker):保存备忘录,但不修改或访问其内容,只负责管理备忘录的生命周期。

# 示例代码

  1. 发起人 备忘录

    public class TextEditor  {
    
        private String content;
    
        public void setContent(String content) {
            this.content = content;
        }
        public String getContent() {
            return content;
        }
    
        // 创建备忘录,保存当前内容
        public Memento save() {
            return new Memento(content);
        }
    
        // 通过备忘录恢复内容
        public void restore(Memento memento) {
            this.content = memento.getContent();
        }
    
        // 备忘录类,保存文本内容状态,封装内部状态
        public static class Memento {
            private final String content;
    
            private Memento(String content) {
                this.content = content;
            }
    
            private String getContent() {
                return content;
            }
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
  2. 管理者

    public class Caretaker {
    
        private Stack<TextEditor.Memento> history = new Stack<>();
    
        // 保存状态
        public void save(TextEditor editor) {
            history.push(editor.save());
        }
    
        // 撤销操作,恢复上一个状态
        public void undo(TextEditor editor) {
            if (!history.isEmpty()) {
                editor.restore(history.pop());
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  3. test

    public class TextEditor  {
    
        private String content;
    
        public void setContent(String content) {
            this.content = content;
        }
        public String getContent() {
            return content;
        }
    
        // 创建备忘录,保存当前内容
        public Memento save() {
            return new Memento(content);
        }
    
        // 通过备忘录恢复内容
        public void restore(Memento memento) {
            this.content = memento.getContent();
        }
    
        // 备忘录类,保存文本内容状态,封装内部状态
        public static class Memento {
            private final String content;
    
            private Memento(String content) {
                this.content = content;
            }
    
            private String getContent() {
                return content;
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

# 中介者模式

中介者模式(Mediator Pattern)通过一个中介对象来封装一系列对象之间的交互,使各对象不直接引用彼此,降低对象之间的耦合,实现松散耦合。在复杂系统中,对象之间相互引用和通信会导致耦合度过高,维护困难。中介者模式通过引入中介者集中管理对象之间的交互,简化通信逻辑。

# 模式定义

  • 抽象中介者(Mediator):定义同事对象通信的接口。
  • 具体中介者(ConcreteMediator):实现中介者接口,协调各同事对象之间的交互。
  • 同事类(Colleague):持有对中介者的引用,通过中介者与其他同事通信。

# 示例代码

  1. 抽象中介者

    public interface Mediator {
        void sendMessage(String message, Colleague colleague);
    }
    
    1
    2
    3
  2. 具体中介者

    public class ChatMediator implements Mediator {
    
        private List<Colleague> colleagues = new ArrayList<>();
    
        // 注册同事
        public void addColleague(Colleague colleague) {
            colleagues.add(colleague);
        }
    
        // 转发消息,发送者之外的同事都会接收
        @Override
        public void sendMessage(String message, Colleague sender) {
            for (Colleague colleague : colleagues) {
                if (colleague != sender) {
                    colleague.receive(message);
                }
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  3. 同事类

    public abstract class Colleague {
    
        protected Mediator mediator;
        public Colleague(Mediator mediator) {
            this.mediator = mediator;
        }
    
        public abstract void receive(String message);
        public abstract void send(String message);
    }
    
    public class User extends Colleague{
    
        private String name;
        public User(String name, Mediator mediator) {
            super(mediator);
            this.name = name;
        }
    
        @Override
        public void receive(String message) {
            System.out.println(name + " 接收到消息: " + message);
        }
    
        @Override
        public void send(String message) {
            System.out.println(name + " 发送消息: " + message);
            mediator.sendMessage(message, this);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
  4. 测试

    public class Test {
    
        public static void main(String[] args) {
            ChatMediator mediator = new ChatMediator();
    
            User user1 = new User("张三", mediator);
            User user2 = new User("李四", mediator);
            User user3 = new User("王五", mediator);
    
            mediator.addColleague(user1);
            mediator.addColleague(user2);
            mediator.addColleague(user3);
    
            user1.send("大家好!");
            user2.send("你好,张三!");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

# 解释器模式

解释器模式(Interpreter Pattern)是为语言创建解释器的一种模式,给定一种语言,定义它的文法表示,并定义一个解释器来解释语言中的句子。当一个特定类型的问题发生的频率足够高时,可以将问题的各个实例表示为一个简单语言的句子。此时使用解释器模式来构造该语言的语法树,并解释执行。

# 模式定义

  • 抽象表达式(AbstractExpression):定义解释操作的接口。
  • 终结符表达式(TerminalExpression):实现与文法中的终结符相关的解释操作。
  • 非终结符表达式(NonTerminalExpression):实现文法中非终结符的解释操作,通常包含对其他表达式的引用。
  • 上下文(Context):包含解释器之外的一些全局信息。

# 示例代码

  1. 抽象表达式

    public interface Expression {
        boolean interpret(Context context);
    }
    
    1
    2
    3
  2. 上下文

    public class Context {
    
        private Map<String, Boolean> variableMap;
    
        public Context(Map<String, Boolean> variableMap) {
            this.variableMap = variableMap;
        }
    
        public boolean getValue(String variable) {
            return variableMap.getOrDefault(variable, false);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  3. 终结符表达式

    public class VariableExpression implements Expression {
    
        private String name;
    
        public VariableExpression(String name) {
            this.name = name;
        }
    
        @Override
        public boolean interpret(Context context) {
            return context.getValue(name);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  4. 非终结符表达式

    public class AndExpression implements Expression{
    
        private Expression left, right;
    
        public AndExpression(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public boolean interpret(Context context) {
            return left.interpret(context) && right.interpret(context);
        }
    }
    
    public class OrExpression implements Expression {
    
        private Expression left, right;
    
        public OrExpression(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public boolean interpret(Context context) {
            return left.interpret(context) || right.interpret(context);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
  5. 测试

    public class Test {
    
        public static void main(String[] args) {
            // 设置变量上下文
            Map<String, Boolean> vars = new HashMap<>();
            vars.put("A", true);
            vars.put("B", false);
            vars.put("C", true);
            Context context = new Context(vars);
    
            // 构建表达式:A AND (B OR C)
            Expression expr = new AndExpression(
                    new VariableExpression("A"),
                    new OrExpression(
                            new VariableExpression("B"),
                            new VariableExpression("C")
                    )
            );
    
            System.out.println("表达式结果:" + expr.interpret(context)); // true AND (false OR true) = true
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

# 观察者模式

观察者模式是一种行为型设计模式,它定义了对象之间一对多的依赖关系,当被观察者状态发生变化时,所有依赖于它的观察者都会自动收到通知并更新。在软件设计中,经常会遇到“一个对象的状态发生变化,其他依赖对象也要随之改变”的场景。使用观察者模式可以将观察者从被观察者中解耦,提高代码的灵活性和可扩展性。

# 模式定义

  • Subject(被观察者):提供注册、注销观察者的方法,以及通知观察者的方法。
  • Observer(观察者):定义更新接口。
  • ConcreteSubject(具体被观察者):状态变化时通知所有注册的观察者。
  • ConcreteObserver(具体观察者):实现接收到通知后的行为。

# 示例代码

  1. 被观察者

    public interface Subject {
    
        void registerObserver(List<Observer> observer);
    
        void removeObserver(Observer observer);
    
        void notifyObserver(String msg);
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  2. 观察者

    public interface Observer {
        // 被观察者, 发生变化更新
        void update(String msg);
    }
    
    1
    2
    3
    4
  3. 具体被观察者

    public class ConcreteSubject implements Subject {
    
        private final List<Observer> observers = new ArrayList<>();
    
        @Override
        public void registerObserver(List<Observer> observer) {
            observers.addAll(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            observers.remove(observer);
        }
    
        @Override
        public void notifyObserver(String msg) {
            for (Observer observer : observers) {
                observer.update(msg);
            }
        }
    
        public void publishEvent(String msg) {
            System.out.println("发出变更消息: " + msg);
            notifyObserver(msg);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
  4. 具体观察者

    public class ConcreteObserver implements Observer{
    
        private final String name;
        public ConcreteObserver(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String msg) {
            System.out.println(name + " 收到变更消息: " + msg);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  5. 测试

    public class Test {
    
        public static void main(String[] args) {
            ConcreteObserver a = new ConcreteObserver("A");
            ConcreteObserver b = new ConcreteObserver("B");
            ConcreteObserver c = new ConcreteObserver("C");
    
            ConcreteSubject subject = new ConcreteSubject();
            subject.registerObserver(List.of(a, b, c));
            subject.publishEvent("变更消息");
            subject.removeObserver(c);
            subject.publishEvent("变更消息1");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

# 访问者模式

访问者模式是一种行为型设计模式,它将数据结构作用于结构上的操作解耦。通过在访问者中封装行为,可以在不改变数据结构的前提下,为其增加新的操作。在某些系统中,稳定的数据结构需要频繁变更其行为逻辑,若将行为写入数据结构中,会导致类职责过重、频繁修改。使用访问者模式,可以在不修改数据结构类的前提下,添加新的操作行为。

# 模式定义

  • Visitor(访问者):声明访问数据结构中各元素的接口。
  • ConcreteVisitor(具体访问者):实现访问操作。
  • Element(元素):声明接受访问者的方法 accept()
  • ConcreteElement(具体元素):实现 accept() 方法。
  • ObjectStructure(对象结构):存储元素集合,并提供访问者访问的方法。

# 示例代码

需求背景:公司有多种员工类型(普通员工、经理),每年 HR 和 财务 部门会对员工进行不同角度的访问分析。访问者模式可以优雅地支持多个访问操作而不污染员工类结构。

  1. Element

    public interface Employee {
        void accept(Visitor visitor);
    }
    
    1
    2
    3
  2. ConcreteElement

    public class Developer implements Employee {
    
        String name;
        int codeLines;
    
        public Developer(String name, int codeLines) {
            this.name = name;
            this.codeLines = codeLines;
        }
    
        public String getName() {
            return name;
        }
    
        public int getCodeLines() {
            return codeLines;
        }
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    public class Manager implements Employee {
    
        String name;
        int productCount;
    
        public Manager(String name, int productCount) {
            this.name = name;
            this.productCount = productCount;
        }
    
        public String getName() {
            return name;
        }
    
        public int getProductCount() {
            return productCount;
        }
    
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
  3. Visitor

    public interface Visitor {
    
        void visit(Developer developer);
        void visit(Manager manager);
    }
    
    1
    2
    3
    4
    5
  4. ConcreteVisitor

    public class FinanceVisitor implements Visitor {
    
        @Override
        public void visit(Developer developer) {
            System.out.println("财务统计开发者:" + developer.getName() + ",年终奖 = " + developer.getCodeLines() * 10);
        }
    
        @Override
        public void visit(Manager manager) {
            System.out.println("财务统计经理:" + manager.getName() + ",年终奖 = " + manager.getProductCount() * 500);
        }
    }
    
    public class HRVisitor implements Visitor {
    
        @Override
        public void visit(Developer developer) {
            System.out.println("HR 查看开发者:" + developer.getName() + ",代码量:" + developer.getCodeLines());
        }
    
        @Override
        public void visit(Manager manager) {
            System.out.println("HR 查看经理:" + manager.getName() + ",管理产品数:" + manager.getProductCount());
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  5. ObjectStructure

    public class EmployeeStructure {
    
        private List<Employee> employees = new ArrayList<>();
    
        public void add(Employee e) {
            employees.add(e);
        }
    
        public void accept(Visitor visitor) {
            for (Employee e : employees) {
                e.accept(visitor);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  6. Test

    public class Test {
    
        public static void main(String[] args) {
            EmployeeStructure structure = new EmployeeStructure();
            structure.add(new Developer("张三", 20000));
            structure.add(new Manager("李四", 4));
    
            Visitor hr = new HRVisitor();
            Visitor finance = new FinanceVisitor();
    
            System.out.println("=== HR 部门访问 ===");
            structure.accept(hr);
    
            System.out.println("=== 财务部门访问 ===");
            structure.accept(finance);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17