访问者模式(Visitor)
从设计原则上来说,它破了对象的封装性,因为访问者模式将被访问对象的相关属性暴露出来并可以操纵它们,即将对象的定义与它的操作进行了拆分
它适用于类的结构相对固定,但是类属性的操作经常发生变化的场景
如果某个类的属性结构时常发生变化 ,那第它一定不适用于访问者模式
UML
具体角色分工
- Visitor:定义为接口或者抽象类,封装了访问所有属性的方法的接口,也是因此要求被访问对象结构要稳定,否则维护成本太高,不适用于此模式
- ConcreteVisitor:具体的访问者对象,对应上面的Comsumer对象,在它里面定义了对被访问对象所有属性的操作方法
- AbstractElement:抽象出来的元素,对应上面的ComputePart,最重要的需要在里面定义一个accept(Visitor visitor)的方法,接受访问者对象对被访问元素的操作
- Element:具体的元素对象,就是通过accept()方法将自己暴露出去,接受访问者的操作
- ObjectStructure:对象结构体,即对应上面的Compute,起到定义具体对象的实际组成的作用
demo
- 对于电脑的抽象,假设里面的原件就三个且固定不变
/**
* @author Xiaoyingge
* @description
* @date 2020/4/26 22:18
*/
public class Compute extends ComputePart {
private CPU cpu;
private Memory memory;
private KeyBroad keyBroad;
public Compute (CPU cpu, Memory memory, KeyBroad keyBroad) {
super(cpu.getPrice() + memory.getPrice() + keyBroad.getPrice());
this.cpu = cpu;
this.memory = memory;
this.keyBroad = keyBroad;
}
@Override
public void accept (Visitor visitor) {
visitor.visit(this);
}
}
- 对元器件做一次抽象
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:29
*/
public abstract class ComputePart {
private int price;
public ComputePart (int price) {
this.price = price;
}
public int getPrice () {
return price;
}
public void setPrice (int price) {
this.price = price;
}
public abstract void accept (Visitor visitor);
}
- CPU
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:31
*/
public class CPU extends ComputePart {
public CPU (int price) {
super(price);
}
@Override
public void accept (Visitor visitor) {
visitor.visitCpu(this);
}
}
- 内存
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:32
*/
public class Memory extends ComputePart {
public Memory (int price) {
super(price);
}
@Override
public void accept (Visitor visitor) {
visitor.visitMemory(this);
}
}
- 键盘
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:31
*/
public class KeyBroad extends ComputePart {
public KeyBroad (int price) {
super(price);
}
@Override
public void accept (Visitor visitor) {
visitor.visitKeyBroad(this);
}
}
- 电脑商店,里面存储了一组组装好的元素集合
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:42
*/
class ComputeStore {
private List<Compute> computes = new ArrayList<>();
public ComputeStore () {
computes.add(new Compute(new CPU(100), new Memory(100), new KeyBroad(100)));
computes.add(new Compute(new CPU(200), new Memory(200), new KeyBroad(200)));
computes.add(new Compute(new CPU(300), new Memory(300), new KeyBroad(300)));
}
public void sell (Visitor visitor) {
for (Compute compute : computes) {
compute.accept(visitor);
}
}
}
- 来了一个顾客,访问者,对他打折!打骨折
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:39
*/
public class Consumer implements Visitor {
@Override
public void visit (Compute compute) {
//整体最终再打上九折
System.out.println("now you price is " + compute.getPrice() * 0.9);
}
@Override
public void visitCpu (CPU cpu) {
System.out.println(cpu.getPrice() * 0.95);
}
@Override
public void visitMemory (Memory memory) {
System.out.println(memory.getPrice() * 0.95);
}
@Override
public void visitKeyBroad (KeyBroad keyBroad) {
System.out.println(keyBroad.getPrice() * 0.95);
}
}
- 测试
/**
* @author xiaoyingge
* @description
* @date 2020/4/26 10:40
*/
public class Main {
public static void main (String[] args) {
ComputeStore store = new ComputeStore();
store.sell(new Consumer());
}
}