您的位置:首页 > 其它

设计模式之十五:访问者模式(Visitor Pattern)

2014-07-07 18:19 381 查看
访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式。据《大话设计模式》中说算是最复杂也是最难以理解的一种模式了。

   定义(源于GoF《Design Pattern》):表示一个作用于某对象结构中的各元素的操作。它使你可以在
不改变各元素类的前提下定义作用于这些元素的新操作。从定义可以看出结构对象是使用访问者模式必备
条件,而且这个结构对象必须存在遍历自身各个对象的方法。这便类似于Java语言当中的collection概念了。
  涉及角色 :
  1.IVisitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和
参数标识了发送访问请求给具休访问者的具休元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
  2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口。
  3.Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
  4.ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
  5.ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:
能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个
复合对象或者一个聚集(如一个列表或无序集合)。
  访问者模式的几个特点:
  访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
  访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。
若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
  访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中
到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。
  适用情况 :
  1) 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  2) 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。
Visitor模式使得你可以将相关的操作集中起来 定义在一个类中。
  3) 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
  4) 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访
问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
public class Body {  
    public void accept(IVisitor visitor) {  
        visitor.visit(this);  
    }  
}  
public class Engine {  
    public  void accept(IVisitor visitor) {  
             visitor.visit(this);  
     }  
}  
public class Wheel {  
    private String name;  
    public Wheel(String name) {  
        this.name = name;  
    }  
    String getName() {  
        return this.name;  
    }  
    public  void accept(IVisitor visitor) {  
        visitor.visit(this);  
    }  
}  
public class Car {  
    private Engine  engine = new Engine();  
    private Body    body   = new Body();  
    private Wheel[] wheels   
        = { new Wheel("front left"), new Wheel("front right"),  
            new Wheel("back left") , new Wheel("back right")  };  
    public void accept(IVisitor visitor) {  
        visitor.visit(this);  
        engine.accept(visitor);  
        body.accept(visitor) ;   
        for (int i = 0; i < wheels.length; ++ i)  
            wheels[i].accept(visitor);  
    }  
}    

public interface IVisitor {  
    void visit(Wheel wheel);  
    void visit(Engine engine);  
    void visit(Body body);  
    void visit(Car car);  
}    
    
public class PrintVisitor implements IVisitor {   
    @Override  
    public void visit(Wheel wheel) {  
        System.out.println("Visiting " + wheel.getName() + " wheel");   
    }    
    @Override  
    public void visit(Engine engine) {  
        System.out.println("Visiting engine");  
    }    
    @Override  
    public void visit(Body body) {  
        System.out.println("Visiting body");  
    }    
    @Override  
    public void visit(Car car) {  
        System.out.println("Visiting car");  
    }   

------------------------例子2-----------------------

Visitor模式,在不修改已有程序结构的前提下,通过添加额外的“访问者”来完成对已有代码功能的提升。Visitor模式的组成结构:

  1) 访问者角色(Visitor):声明一个访问接口。接口的名称和方法的参数标识了向访问者发送请求的元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。

  2) 具体访问者角色(Concrete Visitor):实现访问者角色(Visitor)接口

  3) 元素角色(Element):定义一个Accept操作,它以一个访问者为参数。

  4) 具体元素角色(Concrete Element):实现元素角色(Element)接口。
  5) 对象结构角色(Object Structure):这是使用Visitor模式必须的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口允许访问者角色访问它的元素;可以是一个组合(组合模式)或是一个集合,如一个列表或一个无序集合
public abstract class Customer {

private String customerId;

private String name;

public String getCustomerId() {

    return customerId;

}

public void setCustomerId(String customerId) {

   this.customerId = customerId;

}

public String getName() {

   return name;

}

public void setName(String name) {

   this.name = name;

}

//接受访问者的访问

public abstract void accept(Visitor visitor);


//企业客户
public class EnterpriseCustomer extends Customer {

 private String linkman;

 private String linkTelephone;

 private String registerAddress;

 public String getLinkman() {

    return linkman;

 }

 public void setLinkman(String linkman) {

  this.linkman = linkman;

 }

 public String getLinkTelephone() {

 return linkTelephone;

 }

 public void setLinkTelephone(String linkTelephone) {

 this.linkTelephone = linkTelephone;

 }

 public String getRegisterAddress() {

 return registerAddress;

 }

 public void setRegisterAddress(String registerAddress) {

this.registerAddress = registerAddress;

 }

 @Override

 public void accept(Visitor visitor) {

 //回调访问者对象的方法

         visitor.visitEnterpriseCustomer(this);

  }
}

//个人客户
public class PersonalCustomer extends Customer {

 private String telephone;

 private int age;

 public String getTelephone() {

      return telephone;

 }

 public void setTelephone(String telephone) {

         this.telephone = telephone;

 }

 public int getAge() {

       return age;

 }

 public void setAge(int age) {

          this.age = age;

 }

 @Override

 public void accept(Visitor visitor) {

     //回调访问者对象的方法

     visitor.visitPersonalCustomer(this);

     }
}

/**
 * 访问者接口
 */
public interface Visitor {

    // 访问企业客户,相当于给企业客户添加访问者功能

    public void visitEnterpriseCustomer(EnterpriseCustomer ec);

    //访问个人客户,相当于给个人客户添加访问者的功能

    public void visitPersonalCustomer(PersonalCustomer pc);
}

/**
 * 具体的访问者,实现对客户的偏好分析
 */
public class PredilectionAnalyzeVisitor implements Visitor {

  @Override

  public void visitEnterpriseCustomer(EnterpriseCustomer ec) {

  // TODO 根据以往的购买历史、潜在购买意向,以及客户所在行业的发展趋势、客户的发展趋势等的分析

                System.out.println("现在对企业客户" + ec.getName() + "进行产品偏好分析");

  }

  @Override

  public void visitPersonalCustomer(PersonalCustomer pc) {

             System.out.println("现在对个人客户" + pc.getName() + "进行产品偏好分析");

  }
}

/**
 * 具体的访问者,实现客户提出服务请求的功能
 */
public class ServiceRequestVisitor implements Visitor {

  @Override

public void visitEnterpriseCustomer(EnterpriseCustomer ec) {

        // TODO 企业客户提出的具体服务请求

         System.out.println(ec.getName() + "企业提出服务请求");

}

@Override

public void visitPersonalCustomer(PersonalCustomer pc) {

       // TODO 个人客户提出的具体服务请求

      System.out.println("客户" + pc.getName() + "提出服务请求");

     }
}

public class ObjectStructure {

 /**

  * 要操作的客户集合

  */

 private Collection<Customer> col = new ArrayList<Customer>();

 /**

  * 提供客户端操作的高层接口,具体的功能由客户端传入的访问者决定

  * @param visitor 客户端需要的访问者

  */

 public void handleRequest(Visitor visitor) {

         for(Customer cm : col) {

              cm.accept(visitor);

        }

 }

 /**

  * 组建对象结构,想对象中添加元素

  * 不同的对象结构有不同的构建方式

  * @param ele 加入到对象的结构元素

  */

 public void addElement(Customer ele) {

          this.col.add(ele);

     }
}

public class Client {

 public static void main(String[] args) {

ObjectStructure os = new ObjectStructure();

Customer cml = new EnterpriseCustomer();

cml.setName("钢铁侠");

os.addElement(cml);

Customer cm2 = new EnterpriseCustomer();

cm2.setName("CDE公司");

os.addElement(cm2);

Customer cm3 = new PersonalCustomer();

cm3.setName("美国佬");

os.addElement(cm3);

ServiceRequestVisitor srVisitor = new ServiceRequestVisitor();

os.handleRequest(srVisitor);

PredilectionAnalyzeVisitor paVisitor = new PredilectionAnalyzeVisitor();

os.handleRequest(paVisitor);

  WorthAnalyzeVisitor waVisitor = new WorthAnalyzeVisitor();

  os.handleRequest(waVisitor);

  }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: