大话设计模式二十三章经(二) 访问者模式(Visitor Pattern)

来源:互联网 发布:大数据收集 编辑:程序博客网 时间:2024/05/17 08:10

越狱专业户迈克尔-斯科菲尔德最近手头比较紧,叫来了2个越狱跟班越狱犯甲和越狱犯乙轻轻松松的搞定了阿尔法银行其中的一处保险库,拿到了一笔不菲的财宝,继续他的亡命生涯.整个行动利落干脆,不留一丝痕迹,真可谓越狱偷盗组织多面手!行动前的晚上,参考了设计模式二十三章经第七式--访问者模式,制定了详细周密的行动计划.阿尔法银行的保险库只允许持有授权的许可证才能进去,你银行老板来了没许可证照样不准进,当然每张许可证的权限不一样,在保险库的可操作范围也不一样,米帅搞到了张银行副总王大胖的许可证,当然这许可证是复制版的,原版的还在王大胖那里.王大胖的这张许可证可谓权限强大,可以自由进出阿尔法银行旗下的多家保险库的任何地方,唯一不能进的就是银行老总私人保险库了.顺便把其他的2张复制好的许可证给了越狱犯甲和越狱犯乙.

第二天一大早,斯科菲尔德一伙开始行动.凭着许可证进入了阿尔法银行的其中一个保险库里,保险库里的柜子有很多,斯科菲尔德打开藏有1661年英王查理二世加冕典礼上制成的权仗上镶嵌的"非洲之星第I"钻石那个柜子,拿到了钻石,越狱犯甲的那张许可证只能打开藏有白金的保险柜,越狱犯乙更惨,试来试去最后终于打开个保险柜,里面只有一只皮包,包里空空如也..

下面这段JAVA代码是站在程序的角度上来实现上面的故事中所用到的访问者模式,这里为了便于读者更好的理解该设计模式,全部用中文命名.

//阿尔法银行所有的保险库都必须符合这个标准
      interface 保险库{
          void accept(许可证 许可证实例);
      }

//符合阿尔法银行保险库标准的旗下一家保险库
      class 保险库A implements 保险库{
          private String 非洲之星钻石;
          private String 白金保险柜;
          private String 皮包;

    public 保险库A(String 非洲之星钻石,String 白金保险柜,String 老总二奶照){

           this.非洲之星钻石=非洲之星钻石;

           this.白金保险柜=白金保险柜;

           this.皮包=皮包;

    }
          public void accept(许可证 许可证实例){
                 许可证实例.访问(this);
          }
          public String get非洲之星钻石() {
                return 非洲之星钻石;
          }
          public void set非洲之星钻石(String 非洲之星钻石) {
                this.非洲之星钻石 = 非洲之星钻石;
          }
          public String get白金保险柜() {
                return 白金保险柜;
          }
          public void set白金保险柜(String 白金保险柜) {
                this.白金保险柜 = 白金保险柜;
          }
          public String get皮包() {
                return 皮包;
          }
          public void set皮包(String 皮包) {
                this.皮包 = 皮包;
          }
       }
      //阿尔法银行所有的保险库许可证都必须符合这个标准
        interface 许可证{
              void 访问(保险库 保险库实例);
        }

        //迈克尔拿到的那张许可证 
        class 许可证A implements 许可证{
              public void 访问(保险库 保险库实例){

                       保险库A 保险库A实例=(保险库A)保险库实例;
                       System.out.println("得到"+保险库A实例.get非洲之星钻石());
              }
        }
      //越狱犯甲拿到的那张许可证
         class 许可证B implements 许可证{
              public void 访问(保险库 保险库实例){

                       保险库A 保险库A实例=(保险库A)保险库实例;

                       System.out.println("得到"+保险库A实例.get白金保险柜());
               }
         }
      //越狱犯乙拿到的那张许可证
        class 许可证C implements 许可证{
               public void 访问(保险库 保险库实例){

                       保险库A 保险库A实例=(保险库A)保险库实例;

                       System.out.println("得到"+保险库A实例.get皮包());
               }
        }

   public class Test{
         public static void main(String[] args) {
                保险库A 保险库A实例=new 保险库A("非洲之星钻石","白金保险柜","皮包");
                许可证A 许可证A实例=new 许可证A();
                许可证B 许可证B实例=new 许可证B();
                许可证C 许可证C实例=new 许可证C();
                保险库A实例.accept(许可证A实例);
                保险库A实例.accept(许可证B实例);
                保险库A实例.accept(许可证C实例);
                }
          }

 输出结果为:

       得到非洲之星钻石

       得到白金保险柜

       得到皮包

上面的代码经测试可以正常运行,直接把代码拷到Eclipse里运行即可!

这里总结一下访问者模式,当一个类这里暂且称为类A经常需要更换行为或者添加新的行为的时候,但我们又不想经常修改类A本身,我们可以把一些需要添加的行为定义在新的类中,这些类都符合类A的的访问接口,它们自身可以通过注入类A,来访问类A的一些属性,并且管理和操作这些属性,来实现类A的一些新的行为。