java设计模式---访问者模式

本文介绍访问者模式的基本概念,包括其实现思路、优缺点及应用场景,并通过一个具体示例展示了如何利用访问者模式为不同类型的对象添加新功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

访问者模式实现的基本思路:  定义一个就接口来代表要新加入的功能,为了通用,也就是定义一个通用的功能方法来代表新加入的功能。在对象结构上添加一个方法,作为通用的方法,也就是可以代表要添加的功能,在这个方法中传入具体的实现新功能的对象。在对象实现的具体实现对象中实现这个方法,回调传入具体的实现新功能的对象,就相当于调用到新功能上了。

访问者的功能:能给一系列对象透明第添加新功能,从而避免在维护期间对一系列对象进行修改,而且还能变相实现复用访问者所具有的功能。

访问者模式的本质:预留通路,实现回调。

访问者模式的优缺点:

好的扩展性:能在不修改对象结构的前提下,为对象结构中的元素添加新功能。

好的复用性:可以通过访问者来定义整个对象结构通用的功能,从而提高复用的程度。

分离无关行为:把相关的行为封装在一起,构成一个访问者,这样每个访问者都比较单一。
对象结构很难变化:不适用于对象结构中类经常变化的情况,因为对象结构发生了改变,访问者的接口和访问者得实现都要发生相应的改变,代价太高。

破坏封装:通常需要对象结构开放内部数据给访问者和ObjectStructure,者破坏了对象的封装性。

示例:


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;
         }
 
         /**
          * 接受访问者的访问
          * @param visitor
          */
         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 {

          /**
           * 访问企业客户,相当于给企业客户添加访问者功能
           * @param ec 企业客户对象
           */
          public void visitEnterpriseCustomer(EnterpriseCustomer ec);
          /**
           * 访问个人客户,相当于给个人客户添加访问者的功能
           * @param pc
           */
          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("ABC集团");
                    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);
         }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值