设计模式之访问者模式笔记
- 说明
- Iterator(访问者)
- 目录
- 访问者模式示例类图
- 抽象访问者角色类
- 抽象元素角色类
- 宠物猫类
- 宠物狗类
- 自己类
- 其他人类
- 家类
- 测试类
说明
记录下学习设计模式-访问者模式的写法。JDK使用版本为1.8版本。
Iterator(访问者)
意图:表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义这些元素的新操作。
结构:
其中:
- Visitor(访问者)为该对象结构中 ConcreteElement 的每一个类声明一个 Visit操作。该操作的名字和特征标识了发送 Visit 请求给该访问者的那个类,这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
- ConcreteVisitor (具体访间者)实现每个有 Visitor 声明的操作,每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor 为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
- Element(元素)定义以一个访间者为参数的 Accept 操作。
- ConcreteElement (具体元素)实现以一个访问者为参数的Accept 操作。
- ObjcctStructure (对象结构)能枚举它的元素,可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个组合或者一个集合,如一个列表或一个无序集合。
适用性:
- 对象结构相对稳定,但其操作算法经常变化的程序。
- 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
目录
访问者模式示例类图
以该UML类图实现访问者模式示例。
抽象访问者角色类
package com.example.deesign_patterns.visitor;
//抽象访问者角色类
public interface Person {
//喂食宠物猫
void feed(Cat cat);
//喂食宠物狗
void feed(Dog dog);
}
抽象元素角色类
package com.example.deesign_patterns.visitor;
//抽象元素角色类
public interface Animal {
//接受访问者访问的功能
void accept(Person person);
}
宠物猫类
package com.example.deesign_patterns.visitor;
//宠物猫类,具体元素角色类
public class Cat implements Animal{
@Override
public void accept(Person person) {
person.feed(this);//访问者给宠物猫喂食
System.out.println("好好吃,喵喵喵。。。");
}
}
宠物狗类
package com.example.deesign_patterns.visitor;
//宠物狗类,具体元素角色类
public class Dog implements Animal{
@Override
public void accept(Person person) {
person.feed(this);//访问者给宠物狗喂食
System.out.println("好好吃,汪汪汪。。。");
}
}
自己类
package com.example.deesign_patterns.visitor;
//自己类,具体访问者角色类
public class Owner implements Person{
@Override
public void feed(Cat cat) {
System.out.println("主人喂食猫");
}
@Override
public void feed(Dog dog) {
System.out.println("主人喂食狗");
}
}
其他人类
package com.example.deesign_patterns.visitor;
//其他人类,具体访问者角色类
public class Someone implements Person{
@Override
public void feed(Cat cat) {
System.out.println("其他人喂食猫");
}
@Override
public void feed(Dog dog) {
System.out.println("其他人喂食狗");
}
}
家类
package com.example.deesign_patterns.visitor;
import java.util.ArrayList;
import java.util.List;
//家类,对象结构类
public class Home {
//声明一个集合对象,用来存储元素对象
private List<Animal> nodeList=new ArrayList<Animal>();
//添加元素功能
public void add(Animal animal){
nodeList.add(animal);
}
public void action(Person person){
//遍历集合,获取每一个元素,让访问者访问每一个元素
for(Animal animal:nodeList){
animal.accept(person);
}
}
}
测试类
package com.example.deesign_patterns.visitor;
//测试类
public class Client {
public static void main(String[] args) {
//创建Home对象
Home home=new Home();
//添加元素到Home对象中
home.add(new Cat());
home.add(new Dog());
//创建主人对象
Owner owner=new Owner();
//让主人喂食所有宠物
home.action(owner);
//创建其他人对象
Someone someone=new Someone();
//让其他人喂食所有宠物
home.action(someone);
}
}
好处:
- 扩展性好。在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
- 复用性好。通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
- 分离无关行为。通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
缺点:
- 对象结构变化很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
- 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。