当前位置: 首页 > news >正文

网站项目意义网站开发 业务流程图

网站项目意义,网站开发 业务流程图,wordpress轮播的插件,石家庄优化公司哪家好前言 Visitor模式在日常工作中出场比较少#xff0c;如果统计大家不熟悉的模式#xff0c;那么它榜上有名的可能性非常大。使用频率少#xff0c;再加上很多文章提到Visitor模式都着重于它克服语言单分派的特点上面#xff0c;而对何时应该使用这个模式及这个模式是怎么一…    前言   Visitor模式在日常工作中出场比较少如果统计大家不熟悉的模式那么它榜上有名的可能性非常大。使用频率少再加上很多文章提到Visitor模式都着重于它克服语言单分派的特点上面而对何时应该使用这个模式及这个模式是怎么一点点演讲出来的提之甚少造成很多人对这个模式有种雾里看花的感觉今天跟着老胡我们一起来一点点揭开它的面纱吧。   模式演进   举个例子现在假设我们有一个简单的需求需要统计出一篇文档中的字数、词数和图片数量。其中字数和词数存在于段落中图片数量单独统计。于是乎我们可以很快的写出第一版代码使用了基本抽象的版本abstract class DocumentElement{public abstract void UpdateStatus(DocumentStatus status);}public class DocumentStatus{public int CharNum { get; set; }public int WordNum { get; set; }public int ImageNum { get; set; }public void ShowStatus(){Console.WriteLine(I have {0} char, {1} word and {2} image, CharNum, WordNum, ImageNum);}}class ImageElement : DocumentElement{public override void UpdateStatus(DocumentStatus status){status.ImageNum;}}class ParagraphElement : DocumentElement{public int CharNum { get; set; }public int WordNum { get; set; }public ParagraphElement(int charNum, int wordNum){CharNum  charNum;WordNum  wordNum;}public override void UpdateStatus(DocumentStatus status){status.CharNum  CharNum;status.WordNum  WordNum;}}class Program{static void Main(string[] args){DocumentStatus docStatus  new DocumentStatus();ListDocumentElement list  new ListDocumentElement();DocumentElement e1  new ImageElement();DocumentElement e2  new ParagraphElement(10, 20);list.Add(e1);list.Add(e2);list.ForEach(e  e.UpdateStatus(docStatus));docStatus.ShowStatus();}}运行结果如下非常简单但是细看这版代码会发现有以下问题•所有的DocumentElement派生类必须访问DocumentStatus根据迪米特法则这不是个好现象如果在未来对DocumentStatus有修改这些派生类被波及的可能性极大•统计代码散落在不同的派生类里面维护不方便有鉴于此我们推出了第二版代码   使用了Tpye-Switch的版本   这一版代码中我们摒弃了之前在具体的DocumentElement派生类中进行统计的做法直接在统计类中统一处理public abstract class DocumentElement{//nothing to do now}public class DocumentStatus{public int CharNum { get; set; }public int WordNum { get; set; }public int ImageNum { get; set; }public void ShowStatus(){Console.WriteLine(I have {0} char, {1} word and {2} image, CharNum, WordNum, ImageNum);}public void Update(DocumentElement documentElement){switch(documentElement){case ImageElement imageElement:ImageNum;break;case ParagraphElement paragraphElement:WordNum  paragraphElement.WordNum;CharNum  paragraphElement.CharNum;break;}}}public class ImageElement : DocumentElement{}public class ParagraphElement : DocumentElement{public int CharNum { get; set; }public int WordNum { get; set; }public ParagraphElement(int charNum, int wordNum){CharNum  charNum;WordNum  wordNum;}}class Program{static void Main(string[] args){DocumentStatus docStatus  new DocumentStatus();ListDocumentElement list  new ListDocumentElement();DocumentElement e1  new ImageElement();DocumentElement e2  new ParagraphElement(10, 20);list.Add(e1);list.Add(e2);docStatus.ShowStatus();}}测试结果和第一个版本的代码一样这一版代码克服了第一个版本中统计代码散落具体类依赖统计类的问题转而我们在统计类中集中处理了统计任务。但同时它引入了type-switch, 这也是一个不好的信号具体表现在•代码冗长且难以维护•如果派生层次加多需要很小心的选择case顺序以防出现继承层次较低的类出现在继承层次更远的类前面从而造成后面的case永远无法被访问的情况这造成了额外的精力成本尝试使用重载的版本有鉴于上面type-switch版本的问题作为敏锐的程序员可能马上有人就会提出重载方案“如果我们针对每个具体的DocumentElement写出相应的Update方法不就可以了吗”就像下面这样public class DocumentStatus{//省略相同代码public void Update(ImageElement imageElement){ImageNum;}public void Update(ParagraphElement paragraphElement){WordNum  paragraphElement.WordNum;CharNum  paragraphElement.CharNum;}}//省略相同代码class Program{static void Main(string[] args){DocumentStatus docStatus  new DocumentStatus();ListDocumentElement list  new ListDocumentElement();list.Add(new ImageElement());list.Add(new ParagraphElement(10, 20));list.ForEach(e  docStatus.Update(e));docStatus.ShowStatus();}}看起来很好不过可惜这段代码编译失败编译器会抱怨说不能将DocumentElement转为它的子类这是为什么呢讲到这里就不能不提一下编程语言中的单分派和双分派   单分派与双分派   大家都知道多态是OOP的三个基本特征之一即形如以下的代码public class Father{public virtual void DoSomething(string str){}}public class Son : Father{public override void DoSomething(string str){}}Father son  new Son();son.DoSomething();son 虽然被声明为Father类型但在运行时会被动态绑定到其实际类型Son并调用到正确的被重写后的函数这是多态通过调用函数的对象执行动态绑定。在主流语言比如C#, C 和 JAVA中编译器在编译类函数的时候会进行扩充把this指针隐含的传递到方法里面上面的方法会扩充为void DoSomething(this, string);void DoSomething(this, string);在多态中实现的this指针动态绑定其实是针对函数的第一个参数进行运行时动态绑定这个也是单分派的定义。至于双分派顾名思义就是可以针对两个参数进行运行时绑定的分派方法不过可惜C#等都不支持所以大家现在应该能理解为什么上面的代码不能通过编译了吧上面的代码通过编译器的扩充变成了public void Update(DocumentStatus status, ImageElement imageElement)public void Update(DocumentStatus status, ParagraphElement imageElement)因为C#不支持双分派第二参数无法动态解析所以就算实际类型是ImageElement但是声明类型是其基类DocumentElement也会被编译器拒绝。所以为了在本不支持双分派的C#中实现双分派我们需要添加一个跳板函数通过这个函数我们让第二参数充当被调用对象实现动态绑定从而找到正确的重载函数我们需要引出今天的主角Visitor模式。   Visitor模式   Visitor is a behavioral design pattern that lets you separate algorithms from the objects on which they operate.翻译的更直白一点Visitor模式允许针对不同的具体类型定制不同的访问方法而这个访问者本身也可以是不同的类型看一下UML在Visitor模式中我们需要把访问者抽象出来以方便之后定制更多的不同类型的访问者。抽象出DocumentElementVisitor含有两个版本的Visit方法在其子类中具体定制针对不同类型的访问方法public abstract class DocumentElementVisitor{public abstract void Visit(ImageElement imageElement);public abstract void Visit(ParagraphElement imageElement);}public class DocumentStatus : DocumentElementVisitor{public int CharNum { get; set; }public int WordNum { get; set; }public int ImageNum { get; set; }public void ShowStatus(){Console.WriteLine(I have {0} char, {1} word and {2} image, CharNum, WordNum, ImageNum);}public void Update(DocumentElement documentElement){documentElement.Accept(this);}public override void Visit(ImageElement imageElement){ImageNum;}public override void Visit(ParagraphElement paragraphElement){WordNum  paragraphElement.WordNum;CharNum  paragraphElement.CharNum;}}在被访问类的基类中添加一个Accept方法这个方法用来实现双分派这个方法就是我们前文提到的跳板函数它的作用就是让第二参数充当被调用对象第二次利用多态第一次多态发生在调用Accept方法的时候public abstract class DocumentElement{public abstract void Accept(DocumentElementVisitor visitor);}public class ImageElement : DocumentElement{public override void Accept(DocumentElementVisitor visitor){visitor.Visit(this);}}public class ParagraphElement : DocumentElement{public int CharNum { get; set; }public int WordNum { get; set; }public ParagraphElement(int charNum, int wordNum){CharNum  charNum;WordNum  wordNum;}public override void Accept(DocumentElementVisitor visitor){visitor.Visit(this);}}这里Accept方法就是Visitor模式的精髓通过调用被访问基类的Accept方法被访问基类通过语言的单分派动态绑定了正确的被访问子类接着在子类方法中将第一参数当做执行对象再调用一次它的方法根据语言的单分派机制第一参数也能被正确的动态绑定类型这样就实现了双分派这就是Visitor模式的简单介绍这个模式的好处在于•克服语言没有双分派功能的缺陷能够正确的解析参数的类型尤其当想要对一个继承族群类的不同子类定制访问方法时这个模式可以派上用场•非常便于添加访问者试想如果我们未来想要添加一个DocumentPriceCount需要对段落和图片计费我们只需要新建一个类继承自DocumentVisitor同时实现相应的Visit方法就行希望大家通过这篇文章能对Visitor模式有一定了解在实践中可以恰当的使用。
http://wiki.neutronadmin.com/news/340237/

相关文章:

  • 本地佛山企业网站建设电脑上多了个wordpress
  • 成都建站提供商网页响应式
  • 检察机关门户网站建设情况军事信息化建设网站
  • 公司的网站建设公司北京企业网页制作
  • 广州微网站建设平台做网站有什么好的推荐
  • 济南公司网站建设公司排名太原网站维护
  • 矢量插画的网站北京做网站的公司商集客电话
  • 网站开发小程序定制seo网站优化培训班
  • 有做兼职赚钱的网站吗英文网站seo推广
  • 深圳外贸网站建设制作方法设计公司做网站价格
  • 淮安市网站各大门户网站有哪些
  • 注册网站安全吗企业网站建设专业的
  • 网站开发记什么费用专业网络优化
  • 微魔方建站电力建设集团网站
  • 商业网站 模板石家庄网站系统建设
  • wordpress 大网站猎头公司一般怎么收费的
  • 河北企业建网站小程序开发框架
  • 郑州网站开发外包建工网校官网论坛入口
  • 淘客网站要备案基于wordpress的商城系统
  • 嘉兴模板建站平台wordpress有趣插件
  • 太仓市住房和建设局网站wordpress .net 比较
  • 雪白丰腴做美妇网站建设商城网站
  • 潍坊哪里可以做网站哪里可以下载免费的ppt模板?
  • 网上智慧团建网站山西城乡建设学校报名网站
  • 洪湖网站建设手机网站织梦模板
  • 如何做网站收徒弟网站宜昌网站设计公司
  • 流行用什么做网站wordpress销售页面
  • 网站开发 工具系统软件开发培训机构
  • 制作企业网站页面实训报告网络系统软件应用与维护
  • 网站tdk建设手机怎么开发软件app