访问者模式包含如下角色:
Vistor: 抽象访问者
ConcreteVisitor: 具体访问者
Element: 抽象元素
ConcreteElement: 具体元素
ObjectStructure: 对象结构
访问者模式俗称23大设计模式中最难的一个。除了结构复杂外,理解也比较难。在我们软件开发中我们可能会对同一个对象有不同的处理,如果我们都做分别的处理,将会产生灾难性的错误。对于这种问题,访问者模式提供了比较好的解决方案。访问者模式即表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式。同时我们还需要明确一点那就是访问者模式是适用于那些数据结构比较稳定的,因为他是将数据的操作与数据结构进行分离了,如果某个系统的数据结构相对稳定,但是操作算法易于变化的话,就比较适用适用访问者模式,因为访问者模式使得算法操作的增加变得比较简单了。
package vistor_method_mod;
import org.junit.Test;
/**
* 狗(Element),不同群体(vistor)购买用途不一样,家庭购买为了陪伴,警察局购买为做警犬等
*
* 访问者模式基本介绍
*
* 1)访问者模式(Visitor Pattern),封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
* 2)主要将数据结构与数据操作分离,解决数据结构和操作耦合性问题
* 3)访问者模式的基本工作原理是 :在被访问的类里面加一个对外提供接待访问者的接口
* 4)访问者模式主要应用场景是 :需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时需要避免让这些操作“污染”这些对象的类,可以选用访问者模式解决。
*
* 优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
*
* 缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
*
*/
public class Client {
@Test
public void test(){
FamilyVistor familyVistor = new FamilyVistor();//访问者为家庭
PoliceVistor policeVistor = new PoliceVistor();//访问者为警察局
DogBirds dogBirds = new DogBirds();
dogBirds.setName("中华犬");
dogBirds.setBreed("强壮");
dogBirds.setDisposition("开朗");
dogBirds.setPrice("1000元");
DogBirds dogBirds2 = new DogBirds();
dogBirds2.setName("田园犬");
dogBirds2.setBreed("忠顺");
dogBirds2.setDisposition("温和");
dogBirds2.setPrice("2000元");
DogStructure dogStructure = new DogStructure();//数据结构
dogStructure.add(dogBirds);
dogStructure.add(dogBirds2);
dogStructure.accept(familyVistor); //家庭访问,并且打印
//家庭单位,购买[中华犬]付出的价格为[1000元]
//家庭单位,养[中华犬]目的是作为宠物,性格要求[开朗]
//家庭单位,购买[田园犬]付出的价格为[2000元]
//家庭单位,养[田园犬]目的是作为宠物,性格要求[温和]
System.out.println("-----------------------------------\n");
dogStructure.accept(policeVistor); //家庭访问,并且打印
//警察局单位,购买[中华犬]付出的价格为[1000元]
//警察局单位,养[中华犬]目的是作为警犬,品种要求[强壮]
//警察局单位,购买[田园犬]付出的价格为[2000元]
//警察局单位,养[田园犬]目的是作为警犬,品种要求[忠顺]
System.out.println("-----------------------------------\n");
dogBirds2.accept(policeVistor); //单体接受访问者
}
}
package vistor_method_mod;
/**
* Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。
* 该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
*/
public interface Vistor {
public void getPurpose(DogBirds dogBirds);
public void payPrice(DogBirds dogBirds);
}
package vistor_method_mod;
/**
* ConcreteVisitor: 具体访问者
*/
public class FamilyVistor implements Vistor {
@Override
public void getPurpose(DogBirds dogBirds) {
System.out.println(String.format("家庭单位,购买[%s]付出的价格为[%s]",dogBirds.getName(),dogBirds.getPrice()));
}
@Override
public void payPrice(DogBirds dogBirds) {
System.out.println(String.format("家庭单位,养[%s]目的是作为宠物,性格要求[%s]",dogBirds.getName(),dogBirds.getDisposition()));
}
}
package vistor_method_mod;
/**
* ConcreteVisitor: 具体访问者
*/
public class PoliceVistor implements Vistor {
@Override
public void getPurpose(DogBirds dogBirds) {
System.out.println(String.format("警察局单位,购买[%s]付出的价格为[%s]",dogBirds.getName(),dogBirds.getPrice()));
}
@Override
public void payPrice(DogBirds dogBirds) {
System.out.println(String.format("警察局单位,养[%s]目的是作为警犬,品种要求[%s]",dogBirds.getName(),dogBirds.getBreed()));
}
}
package vistor_method_mod;
/**
* Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
*/
public abstract class Birds {
private String name;
//品种
private String breed;
//性格
private String disposition;
public abstract void accept(Vistor vistor);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getDisposition() {
return disposition;
}
public void setDisposition(String disposition) {
this.disposition = disposition;
}
}
package vistor_method_mod;
/**
* ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
*/
public class DogBirds extends Birds {
//价格
private String price;
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public void accept(Vistor vistor) {
vistor.getPurpose(this);
vistor.payPrice(this);
}
}
package vistor_method_mod;
import java.util.ArrayList;
import java.util.List;
/**
* ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
* 若结构简单,不一定要使用
*/
public class DogStructure {
List<DogBirds> dogStructureList = new ArrayList<DogBirds>();
public void accept(Vistor vistor){
for (DogBirds dogBirds : dogStructureList){
dogBirds.accept(vistor);
}
}
public void add(DogBirds dogBirds){
dogStructureList.add(dogBirds);
}
}