文章目录
- 1、访问者模式
- 2、案例:宠物喂食
- 3、总结
1、访问者模式
封装一些作用于某种容器中各个元素的操作。相关角色:
- 抽象访问者:定义了对每一类元素访问的行为。方法个数等于具体元素类的个数,方法形参是可访问的元素。
- 具体访问者:实现类,重写定义对每一类元素访问时所产生的具体行为
- 抽象元素类:定义一个接收访问者的方法,方法形参为抽象访问者
- 具体元素类:实现类,重写元素类在接受访问者访问时对应的具体行为
- 对象结构角色:一个容器,包含一组元素,可迭代元素,让访问者去访问
2、案例:宠物喂食
给宠物喂食,宠物可以是猫、狗,喂食的人可以是主人、其他人。角色对应:
- 访问者角色:给宠物喂食的人(两个具体元素,两个feed方法)
- 具体访问者角色:主人、其他人
- 抽象元素角色:动物抽象类
- 具体元素角色:宠物狗、宠物猫
- 结构对象角色:主人家
创建抽象访问者接口:
public interface Person {void feed(Cat cat);void feed(Dog dog);
}
创建不同的具体访问者角色(主人和其他人),都需要实现 Person
接口:
public class Owner implements Person {@Overridepublic void feed(Cat cat) {System.out.println("主人喂食猫");}@Overridepublic void feed(Dog dog) {System.out.println("主人喂食狗");}
}
public class Someone implements Person {@Overridepublic void feed(Cat cat) {System.out.println("其他人喂食猫");}@Overridepublic void feed(Dog dog) {System.out.println("其他人喂食狗");}
}
定义抽象元素角色类 – 宠物,里面有一个接受访问者访问的方法,形参为访问者角色类
public interface Animal {void accept(Person person);
}
定义实现Animal
接口的 具体元素角色类:宠物狗和宠物猫
public class Dog implements Animal {@Overridepublic void accept(Person person) {person.feed(this);System.out.println("好好吃,汪汪汪!!!");}
}
public class Cat implements Animal {@Overridepublic void accept(Person person) {person.feed(this);System.out.println("好好吃,喵喵喵!!!");}
}
定义对象结构类,此案例中就是主人的家。声明一个集合,用来存储元素对象
public class Home {private List<Animal> nodeList = new ArrayList<Animal>();public void action(Person person) {for (Animal node : nodeList) {node.accept(person);}}//添加操作public void add(Animal animal) {nodeList.add(animal);}
}
测试类:
public class Client {public static void main(String[] args) {Home home = new Home();home.add(new Dog());home.add(new Cat());Owner owner = new Owner();home.action(owner);//Someone someone = new Someone();//home.action(someone);}
}
3、总结
优点:
-
扩展性好
在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
-
复用性好
通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
-
分离无关行为
通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
缺点:
-
对象结构变化很困难
在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
-
违反了依赖倒置原则
访问者模式依赖了具体类,而没有依赖抽象类。
使用场景:
-
对象结构相对稳定,但其操作算法经常变化的程序。
-
对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。