设计模式的理解: 访问器模式 Visitor

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

在软件构建过程中,由于需求的改变,某些类层次结构中需要增加新的行为,如果这些操作在基类中进行更改,那么派生类也要做出响应的变更,给变更工作带来繁重的负担。访问器模式,就是把原来基类和派生类的实现放在访问器类中,各个派生类访问这些访问器的操作方法。而访问器中的操作方法接受派生类的实体,对派生类的属性进行操作。这样要变更操作方法只需要变更具体的访问器,而不需要变更基类和派生类。

以文件流和网络流为例, 其访问器模式 ,流的实现结构如下:

/*********建立稳定的实体类和抽象访问器类************/
class IVisitor{
public:
     virtual void visitFileStream(FileStream & )=0;
     virtual void visitNetWorkStream(NetWorkStream &)=0;
}
class IStream{
public:
   void acceptVisitor(IVisitor&) = 0;
}
class FileStream : public IStream{
public:
    File file_;
    void acceptVisitor(IVisitor& v){  v.visitFileStream(*this);}
}
class NetWorkStream : public IStream{
public:
    string  url_;
    void acceptVisitor(IVisitor& v){  v.visitNetWorkStream(*this);}
}

假如:流的功能有 读和写  , 那么 读操作和写操作不再 流对象中实现,而是把这些操作变成一个类的对象,这个类的对象派生自访问器类

/*****给流添加读写操作,(用伪码演示)*****/
class ReadStreamVisitor :IVisitor{
    string output_;    
public:
     virtual void visitFileStream(FileStream &fs){
          File  file  = fs.file_;
            ....
          output_=file.getcontent();
     }
     virtual void visitNetWorkStream(NetWorkStream & ns){
          NetwoarkRequest NetwoarkRequest(ns.url_);
          ...
          output_=NetwoarkRequest.getcontent();
     }
}

class WriteStreamVisitor :IVisitor{
public:
     string inputstr_;        //输入参数可以用Visitor存
public:
     virtual void visitFileStream(FileStream &fs){
          File  file  = fs.file_;
            ....
          file.write(inputstr_);
     }
     virtual void visitNetWorkStream(NetWorkStream & ns){
          NetwoarkRequest NetwoarkRequest(ns.url_);
          ...
          NetwoarkRequest.write(inputstr_);
     }
}

调用示例:

void main(){
   //读取网络内容
    NetWorkStream ns;
    ns.url_ = "www.baidu.com";
    ReadStreamVisitor  readVisitor;
    ns.accept(readVisitor);
    cout<<"网络读取的内容有:" <<readVisitor.output_;
    
   //写文件内容
    File file("C:/test.txt");
    FileStream fs(file);
    WriteStreamVisitor writeVisitor;
    writeVisitor.inputstr_ = "写入一些文本"'
    fs.accept(WriteStreamVisitor );
}

如果需求要求变更写操作方法,那么只需要变动WriteStreamVisitor中的方法而不需要变动其他类。如果需求要求新增一个流方法,只需要新增一个Visitor派生类就可以。而不需要从基类从派生类从下至上的修改,造成业务需求的变更影响范围大。

当然,访问者模式只适合类的层次结构稳定,操作扩展变动频繁的业务场景。所谓的层次结构稳定就是实体类的关系很少根据需求而变化。例如如果新增一个 DataBaseStream,那么每个Visitor都要再实现关于DataBaseStream的操作。访问者模式的目的就是为了减少 实体和实体方法间的耦合程度,减小变更实体方法的影响性。如果层次结构不稳定,那么使用访问者模式就得不偿失.

 

おすすめ

転載: blog.csdn.net/superSmart_Dong/article/details/115579793