设计模式的理解: 访问器模式 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<<"网络读取的内容有:" <
如果需求要求变更写操作方法,那么只需要变动WriteStreamVisitor中的方法而不需要变动其他类。如果需求要求新增一个流方法,只需要新增一个Visitor派生类就可以。而不需要从基类从派生类从下至上的修改,造成业务需求的变更影响范围大。
当然,访问者模式只适合类的层次结构稳定,操作扩展变动频繁的业务场景。所谓的层次结构稳定就是实体类的关系很少根据需求而变化。例如如果新增一个 DataBaseStream,那么每个Visitor都要再实现关于DataBaseStream的操作。访问者模式的目的就是为了减少 实体和实体方法间的耦合程度,减小变更实体方法的影响性。如果层次结构不稳定,那么使用访问者模式就得不偿失.
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
