mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-11-01 19:53:43 +00:00
Update 设计模式 - 访问者.md
调整意图描述并补充类图中的角色说明;在实现小节补充双分派机制与适用场景说明,并完成代码与文字校对。
This commit is contained in:
+17
-7
@@ -1,16 +1,26 @@
|
||||
## 访问者(Visitor)
|
||||
|
||||
### 意图
|
||||
为一个对象结构(比如组合结构)增加新能力。
|
||||
在不修改元素类的前提下,为一个对象结构(比如组合结构)中的元素增加新的操作。
|
||||
|
||||
### 类图
|
||||
- Visitor:访问者,为每一个 ConcreteElement 声明一个 visit 操作
|
||||
- ConcreteVisitor:具体访问者,存储遍历过程中的累计结果
|
||||
- Visitor:访问者,为每一个 ConcreteElement 声明一个 visit 操作;
|
||||
- ConcreteVisitor:具体访问者,存储遍历过程中的累计结果;
|
||||
- Element:元素,声明 accept(Visitor) 方法;
|
||||
- ObjectStructure:对象结构,可以是组合结构,或者是一个集合。
|
||||
|
||||
<div align="center"> <img src="pics/dp-visitor.png" width="780px"/> </div><br>
|
||||
|
||||
### 实现
|
||||
下面的例子用一个 GeneralReport 访问者统计客户、订单和商品的数量。元素的 accept() 中调用 visitor.visit(this),这次调用经过两次分派才落到正确的代码上:
|
||||
|
||||
- 第一次,customer.accept(visitor) 按元素的实际类型选中 Customer 的 accept();
|
||||
- 第二次,accept() 中 this 的类型是 Customer,编译时选中 visit(Customer) 这个重载(重载按静态类型选择,见[多态](面向对象思想.md#多态)),运行时再按访问者的实际类型调用 GeneralReport 的实现。
|
||||
|
||||
这种做法称为双分派(Double Dispatch)。
|
||||
|
||||
新增一种报表只需要再写一个 Visitor 实现,Customer、Order、Item 都不用改;代价是新增一种元素时要修改 Visitor 接口和所有访问者,因此访问者适合元素类型稳定、操作经常增加的场景。
|
||||
|
||||
```java
|
||||
public interface Element {
|
||||
void accept(Visitor visitor);
|
||||
@@ -65,7 +75,7 @@ public class Customer implements Element {
|
||||
public class Order implements Element {
|
||||
|
||||
private String name;
|
||||
private List<Item> items = new ArrayList();
|
||||
private List<Item> items = new ArrayList<>();
|
||||
|
||||
Order(String name) {
|
||||
this.name = name;
|
||||
@@ -198,10 +208,10 @@ Number of items: 6
|
||||
```
|
||||
|
||||
### JDK 中的应用
|
||||
- javax.lang.model.element.Element and javax.lang.model.element.ElementVisitor
|
||||
- javax.lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor
|
||||
- javax.lang.model.element.Element 与 javax.lang.model.element.ElementVisitor;
|
||||
- javax.lang.model.type.TypeMirror 与 javax.lang.model.type.TypeVisitor。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- 弗里曼. Head First 设计模式 [M]. 中国电力出版社, 2007.
|
||||
- Gamma E. 设计模式: 可复用面向对象软件的基础 [M]. 机械工业出版社, 2007.
|
||||
- Gamma E. 设计模式:可复用面向对象软件的基础 [M]. 机械工业出版社, 2007.
|
||||
|
||||
Reference in New Issue
Block a user