设计模式---05.访问者模式

付威     2020-03-22   6840   19min  

访问者模式

访问者模式是一种对象和对象的访问者分开的一种设计模式,在一个对象稳定的情况下,使用访问者模式可以更好的扩展对数据的访问。 相当于是我们在对象里面安插了一个“眼”,这个眼能够被外面实现,然后能拿到当前对象的各个属性。

举个例子

组装一台电脑,对于组装的对于组装者来说,只关心一个电脑零件构成(CPU,内存,鼠标键盘)。而对于电脑的消费者,关心的是电脑各个零件的价格以及总价。 而对于有些人来说对于,可能只关心电脑各个零件的重要性以及核心程度。综上所述我们操作的对象是一个电脑,对象是不变的,电脑的访问者来说是不同的,他们从不同的维度来分析这个电脑的属性。下面我们就用类图来表示访问者模式的大概结构:

访问者模式

对于访问者模式来说有以下几个实现步骤:

  1. 定义一个对象(可以是一个基类,也可是其他)

      public class ComputerPartBase   {
           private final String partName;
           private final int coreLevel;
           private final double price;
              
           public ComputerPartBase(String partName, int coreLevel, double price) {
                this.partName = partName;
                this.coreLevel = coreLevel;
                this.price = price;
           }
              
           public String getPartName() {
                return partName;
           }
              
           public int getCoreLevel() {
                return coreLevel;
           }
              
           public double getPrice() {
                return price;
           }
     
      }
    
    
  2. 定义一个接口,实现”插眼”的约束

     public interface ComputerVisitor {
       public void accept(ComputerPartVisitor computerPartVisitor);
      }
    
  3. 对象继承”眼“,实现方法

    public class ComputerPartBase implements ComputerVisitor {
    	 
       //.....
    	
     @Override
     public void accept(ComputerPartVisitor computerPartVisitor) {
    	
        }
     }
    
  4. 各个零件的实现

      public class CPU  extends ComputerPartBase {
           public CPU() {
                super("CPU", 10,2000.00d);
           }
              
           @Override
           public void accept(ComputerPartVisitor computerPartVisitor) {
                computerPartVisitor.visit(this);
           }
      }
    
      public class Keyboard extends ComputerPartBase implements ComputerVisitor {
           public Keyboard() {
                super("keyboard", 1, 10);
           }
              
           @Override
           public void accept(ComputerPartVisitor computerPartVisitor) {
                computerPartVisitor.visit(this);
           }
      }
    
      public class Memery extends ComputerPartBase implements ComputerVisitor {
           public Memery() {
                super("memery", 8, 200d);
           }
              
           @Override
           public void accept(ComputerPartVisitor computerPartVisitor) {
                computerPartVisitor.visit(this);
           }
     }
    
      public class Monitor extends ComputerPartBase implements ComputerVisitor {
           public Monitor() {
                super("monitor", 2, 800);
           }
              
           @Override
           public void accept(ComputerPartVisitor computerPartVisitor) {
                computerPartVisitor.visit(this);
           }
      }    
    
      public class Mouse extends ComputerPartBase implements ComputerVisitor {
           public Mouse() {
                super("mouse", 2, 100);
           }
              
           @Override
           public void accept(ComputerPartVisitor computerPartVisitor) {
                computerPartVisitor.visit(this);
           }
      }
    
    
  5. 真正的”眼“的接口

    
      public interface ComputerPartVisitor {
           public void visit(CPU cpu);
           public void visit(Memery memery);
           public void visit(Mouse mouse);
           public void visit(Keyboard keyboard);
           public void visit(Monitor monitor);
      }
    
    
  6. 访问者通过实现来获取数据

      //电脑的组成
      public class ComputerPartStrutchNameVisitor implements ComputerPartVisitor {
         
           private List<String> partSet=new ArrayList<>();
           @Override
           public void visit(CPU cpu) {
                partSet.add(cpu.getPartName());
           }
              
           @Override
           public void visit(Memery memery) {
                partSet.add(memery.getPartName());
                   
           }
              
           @Override
           public void visit(Mouse mouse) {
                partSet.add(mouse.getPartName());
                   
           }
              
           @Override
           public void visit(Keyboard keyboard) {
                partSet.add(keyboard.getPartName());
                   
           }
              
           @Override
           public void visit(Monitor monitor) {
                partSet.add(monitor.getPartName());
                   
           }
              
           public String getNeedPart(){
                return partSet.stream().collect(Collectors.joining(","));
           }
      }
    
    
    
      //电脑的组装价格
      public class ComputerPartPriceVisitor implements ComputerPartVisitor {
                   
                private double price = 0d;
                   
                @Override
                public void visit(CPU cpu) {
                     price += cpu.getPrice();
                }
                   
                @Override
                public void visit(Memery memery) {
                     price += memery.getPrice();
                        
                }
                   
                @Override
                public void visit(Mouse mouse) {
                     price += mouse.getPrice();
                }
                   
                @Override
                public void visit(Keyboard keyboard) {
                     price += keyboard.getPrice();
                        
                }
                   
                @Override
                public void visit(Monitor monitor) {
                     price += monitor.getPrice();
                }
                public double getPrice(){
                     return price;
                }
      }
    
    
      //获得电脑的核心等级
      public class ComputerPartCoreLevelVisitor implements ComputerPartVisitor {
    	
           private List<String> levelList = new ArrayList<>();
              
           @Override
           public void visit(CPU cpu) {
                   
                levelList.add("CPU:"+cpu.getCoreLevel());
           }
              
           @Override
           public void visit(Memery memery) {
                levelList.add("Memery:"+memery.getCoreLevel());
           }
              
           @Override
           public void visit(Mouse mouse) {
                levelList.add("Mouse:"+mouse.getCoreLevel());
           }
              
           @Override
           public void visit(Keyboard keyboard) {
                levelList.add("Keyboard:"+keyboard.getCoreLevel());
           }
              
           @Override
           public void visit(Monitor monitor) {
                levelList.add("Monitor:"+monitor.getCoreLevel());
           }
           public String getCoreLevel(){
                return levelList.stream().collect(Collectors.joining(","));
           }
      }
    
    
  7. 调用的实现

    public class AppMain {
      public static void main(String[] args) {
           Computer computer = new Computer();
           ComputerPartStrutchNameVisitor computerPartVisitor = new ComputerPartStrutchNameVisitor();
           computer.accept(computerPartVisitor);
           System.out.println("组装一个电脑需要零件:" + computerPartVisitor.getNeedPart());
              
           ComputerPartPriceVisitor computerPartPriceVisitor = new ComputerPartPriceVisitor();
           computer.accept(computerPartPriceVisitor);
           System.out.println("组装一个电脑需要Money:" + computerPartPriceVisitor.getPrice());
              
           ComputerPartCoreLevelVisitor computerPartCoreLevelVisitor = new ComputerPartCoreLevelVisitor();
           computer.accept(computerPartCoreLevelVisitor);
           System.out.println("电脑硬件的核心优先级为:" + computerPartCoreLevelVisitor.getCoreLevel());
      }
    }  
    
    

输出的结果为:

 组装一个电脑需要零件:CPU,memery,monitor,keyboard,mouse
 组装一个电脑需要Money:3110.0
 电脑硬件的核心优先级为:CPU:10,Memery:8,Monitor:2,Keyboard:1,Mouse:2
(本文完)

作者:付威

博客地址:http://blog.laofu.online

如果觉得对您有帮助,可以下方的RSS订阅,谢谢合作

如有任何知识产权、版权问题或理论错误,还请指正。

本文是付威的网络博客原创,自由转载-非商用-非衍生-保持署名,请遵循:创意共享3.0许可证

交流请加群113249828: 点击加群   或发我邮件 laofu_online@163.com

付威

获得最新的博主文章,请关注上方公众号