论坛首页 Java企业应用论坛

Visitor - 访问者模式

浏览 13014 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-08   最后修改:2008-12-08
wangdi 写道
引用
当然,Visitor也有它自身的限制。它不适合于业务数量的经常变化,因为一旦新增或删除一些Service时,需要对visitor进行相应的增删。也就是说具体Service与Visitor是耦合的。
其实,我非常想知道关于visitor模式的定义,,有了准确定义,实现应该会比较简单。
注:我这儿的accept()、process()方法和lz的对应的方法是不一样的。。
public interface IVisitor {
    public void accept(IService service);
}

public interface IService {
    public void process(IVisitor vistor);
}

public class Fund implements IService {
    public void process(IVisitor vistor){
        System.out.println("处理" + this);
    }
    
    public String toString(){
        return "基金业务";
    }
}

public class Saving implements IService {
    public void process(IVisitor vistor) {
        System.out.println("处理" + this);
    }

    public String toString() {
        return "存款业务";
    }
}

public class Visitor implements IVisitor {
    public void accept(IService service) {
        service.process(this);
    }
}

public class VisitorClients0 {
    public static void main(String[] args) {
        IVisitor visitor = new Visitor();
        
        IService fundService = new Fund();
        IService savingService = new Saving();
        
        visitor.accept(fundService);
        visitor.accept(savingService);
    }
}


网上关于访问者大多数定义都像楼主所举的。 但是访问者模式,重点是 不改变原有的类与类继承关系上,为原有的类体系增加新的功能

这是类图.由于163的也是一个减化图,因此自已重新传一张,进行说明


上图中ObjectStructure所指示的 类结构,是固定的,是不希望发生变化的。但是,这个类的各个子类,他们要经常增加新的功能或操作。如何不改变这个类结构,又能在原有的基础上增加新的操作呢?  则这些子类ConcreateElenmentA、ConcreateElenmentB 预先调用一个功能扩展方法(即accept).如果没有功能变化,这个对象就是null,或有他是其方法中的是一个空语句。 而这个功能扩展方法,有一个参数-------Vistor对象, 这个对象装载着新功能变化。Vistor类的方法,对应着Element中各个子类,使用了accept方法的方法,如果当Element中的某个子类如ConcreateElenmentA,要增加功能了,则把新功能写在Vistor子类中.具体作法是,单写一个类,让它继承Vistor,由于这里是增加ConcreateElenmentA的功能,则在自已写的这个类中覆盖VistorConcreateElenmenA方法就行了。然后把自已写的类,生成一个实例,传递给ConcreateElenmentA对象.

简单说:

      1   Element 类继承体系中,其继承关系不变,各个子类不变。但是,各个子类的却经常需要增加新功能。

         -----------这是我们的想要达到的目的。

      2  实现方法:  先定义一套方法封装在vistor类中。这套方法中,每个方法对应着一个Element子类。Element子类则在事先在代码中,谳用这个vistor对象中与自已相对应的方法。而accept方法,就是传输管道。 
        当用户要增加 Element的子类ConcreateElenmentA时,具体使用如下:
        (1) 写一个 Vistor1继承Vistor。 Vistor1中,覆盖VistorConcreateElenmenA方法,写新加入的功能。
        (2)生成Vistor1的实例。其名取为vistor1
        (3)生成ConcreateElenmentA的实例,取名 concreateElenmentA
        (4)定义一个 Element变量,名为e,其值为vistor1 ;  定义一个Vistor变量,名为v,其值为concreateElenmentA
        (5) 用如下语句增加ConcreateElenmentA的实例的功能。 e.accpt(v)
        (6) 当ConcreateElenmentA的实例的功能又变化了,则 修改第一条与第四条。重写一个Vistor的子类,并赋值给变量v即可。  其他代码根本不用改变了。出色的达到了我们想要的目的.
     
      3 这个场景可用spring的AOP
      4 题化话------ 访问者名字的由来。也许是Element的各个子类---------为来访的客人预留下了座位。来访客人每次带一大包实用的礼物,让Element的子类的实例增加自已的魔法功能。来访的客人各不相同,带来的礼物五花八门,于是Element的子类的实例,展现出魔术般的神奇效果。

    
======================================================
以上是三年前对 vitor的个人理解。尘封了N久的记忆,总算被打开了。说事在的,二十三种模式,仅有少数几种留下了深刻的印像,其余的都淡忘掉了。唯独模式设计的封装变化点在心中。好在,还有自已能看懂的笔记一直保存着。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics