Java设计模式全集-访问者模式(Visitor)

访问者模式(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());
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值