# 行为型模式
作者:Ethan.Yang
博客:https://blog.ethanyang.cn (opens new window)
相关代码参考: 设计模式代码仓库 (opens new window)
# 委派模式
允许对象组合实现与继承相同的代码重用, 基本作用是负责任务的调用和分配
# 模式定义与角色
- 抽象任务角色: 定义一个抽象接口, 有若干实现类
- 委派者角色: 负责在各个具体角色实例之间做出决策, 并判断并调用具体实现的方法
- 具体任务角色: 真正执行任务的角色
# 委派模式的实现
抽象任务角色
public interface Employee { void doTask(String task); }1
2
3
4具体任务角色
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委派者角色
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发任务
public class Boss { public void command(String task, Leader leader) { leader.doTask(task); } }1
2
3
4
5
6测试
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
# 模板方法模式
定义一个操作中的算法框架, 将一些步骤延迟到子类, 使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。
# 模式定义与角色
- 抽象模板: 定义了一套算法框架/流程
- 具体实现: 对算法框架/流程的某些步骤进行了实现
- 钩子方法: 可选的扩展点, 子类自行决定是否重写
# 模板方法的实现
抽象模板
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具体实现
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测试
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
# 策略模式
将定义的算法家族分别封装, 让他们之间可以互相替换, 从而实现同一行为在不同场景下具备不同实现
# 模式定义与角色
- 抽象策略角色: 规定策略或算法的行为
- 具体策略角色: 具体的策略或算法实现
- 上下文角色: 用来操作策略的上下文环境, 屏蔽高层模块对策略的直接访问
# 策略模式的实现
抽象策略角色
public interface PayStrategy { void pay(double amount); }1
2
3
4具体策略角色
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策略上下文
public interface PayStrategy { void pay(double amount); }1
2
3
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
# 责任链模式
将链中的每一个节点看做一个对象, 每个节点处理的请求均不同, 且内部自动维护一个下一节点对象。当一个请求从链的首端发出, 会沿着链的路径依次传递给每一个节点对象, 直至有对象处理这个请求为止。
# 模式定义与角色
- 抽象处理者: 定义一个请求处理的方法, 并维护一个下一个处理节点Handler对象的引用。
- 具体处理者: 对请求进行处理, 如果不感兴趣则进行转发。
# 责任链模式的实现
看一个登录校验案例
@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");
}
}
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
用责任链模式改造:
抽象处理者
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具体处理者
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改造原有流程
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
# 迭代器模式
提供一种顺序访问集合/容器对象元素的方法, 无须暴露集合内部表示, 为不同的集合提供一致的遍历行为, 不用关心容器内部元素的组成结构。
# 模式定义与角色
- 抽象迭代器: 抽象迭代器负责定义访问和遍历元素的接口
- 具体迭代器: 提供具体的元素遍历行为
- 抽象容器: 负责定义提供具体迭代器的接口
- 具体容器: 创建具体迭代器
# 迭代器模式的实现
抽象迭代器
public interface Iterator<E> { boolean hasNext(); E next(); }1
2
3
4
5抽象容器
public interface Aggregate<E> { Iterator<E> createIterator(); }1
2
3
4具体迭代器
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具体容器
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):创建命令对象并设置调用者和接收者之间的关系。
# 示例代码
命令
public interface Command { void execute(); }1
2
3
4接收者
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具体命令
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调用者
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测试
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(具体状态):实现具体状态下的行为逻辑,并可切换至其他状态。
# 示例代码
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状态接口
public interface State { void handle(Context context); }1
2
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测试
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):保存备忘录,但不修改或访问其内容,只负责管理备忘录的生命周期。
# 示例代码
发起人 备忘录
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管理者
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
16test
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):持有对中介者的引用,通过中介者与其他同事通信。
# 示例代码
抽象中介者
public interface Mediator { void sendMessage(String message, Colleague colleague); }1
2
3具体中介者
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同事类
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测试
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):包含解释器之外的一些全局信息。
# 示例代码
抽象表达式
public interface Expression { boolean interpret(Context context); }1
2
3上下文
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终结符表达式
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非终结符表达式
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测试
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(具体观察者):实现接收到通知后的行为。
# 示例代码
被观察者
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观察者
public interface Observer { // 被观察者, 发生变化更新 void update(String msg); }1
2
3
4具体被观察者
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具体观察者
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测试
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 和 财务 部门会对员工进行不同角度的访问分析。访问者模式可以优雅地支持多个访问操作而不污染员工类结构。
Element
public interface Employee { void accept(Visitor visitor); }1
2
3ConcreteElement
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
47Visitor
public interface Visitor { void visit(Developer developer); void visit(Manager manager); }1
2
3
4
5ConcreteVisitor
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
25ObjectStructure
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
14Test
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
← 结构型模式