Visitor - 访问者模式
Visitor Pattern in Groovy
Visitor Pattern in GroovyGroovy是一种支持面向对象、函数式编程的动态语言。
其中一种常用的设计模式是访问者模式(Visitor Pattern)。
访问者模式是一种用于数据结构处理的设计模式,它能够将算法与数据结构分离。
访问者模式的本质是将数据结构和数据操作分离,使得操作可以独立变化。
在访问者模式中,数据结构被封装在一个访问者对象中,并且这个对象可以被多个不同的操作所共享。
当一个操作需要对数据结构进行处理时,它可以通过访问者对象来访问数据结构中的元素。
在Groovy中,我们可以通过使用闭包(Closure)来实现访问者模式。
闭包是一种能够捕获作用域内的变量,并将其保存在一个可调用对象中的特殊函数。
闭包可以用来表示一段代码块,并在后续的执行中被调用。
下面是一个使用闭包实现访问者模式的例子:```groovyclass Element {void accept(Closure closure) {closure.call(this)}}class ConcreteElement extends Element {String getName() { "ConcreteElement" }}class Visitor {void visit(Element element) {println "Visit ${}: ${element.getName()}" }}class ConcreteVisitor extends Visitor {void visit(ConcreteElement element) {println "Visit ConcreteElement: ${element.getName()}"}}def element = new ConcreteElement()def visitor = new ConcreteVisitor()element.accept(visitor.&visit)```在这个例子中,我们定义了Element和ConcreteElement两个类。
visit设计模式
visit设计模式访问者模式是一种软件设计模式,它提供了一种在不需要改变各类的前提下定义新的操作方式的方法。
它属于行为模式。
一个场景是,你有一堆对象,每个对象都有一些属性和方法,但它们属于不同的类,很难再添加新的操作。
那么,你可以使用访问者模式。
在访问者模式中,有一个通用的操作,这个操作并不代表任何具体的功能,只是构成一个调用的通路。
访问者提供这个通用的操作(例如:visit),而对象提供接受这个操作的方法(例如:accept)。
在accept方法里面回调visit方法,从而回调到访问者的具体实现,而这个访问者的具体实现的方法就是要添加的新的功能。
以下是访问者模式的基本组成部分:1. 访问者(Visitor):这是一个抽象类,定义了一个或多个方法,这些方法对应于元素的某些操作。
2. 具体访问者(ConcreteVisitor):这是访问者类的一个实现,它提供了访问者类中方法的具体实现。
3. 元素(Element):这是一个接口,定义了接受访问的方法。
4. 具体元素(ConcreteElement):这是元素类的一个实现,它实现了元素接口中定义的方法。
5. 对象结构(ObjectStructure):这是包含多个元素的类。
此外,还有两次分发技术。
当客户端调用ObjectStructure的时候,会遍历ObjectStructure中所有的元素,调用这些元素的accept方法,让这些元素来接收访问,这是请求的第一次分发;在具体的元素对象中实现accept 方法的时候,会回调访问者的visit方法,等于请求被第二次分发了,请求被分发给访问者来处理,真正实现功能的正式访问者的visit方法。
此外,访问者模式一个很常见的应用就是和组合模式结合使用,通过访问者模式来给由组合模式构建的对象结构增加功能。
以上内容仅供参考,如需更多信息,建议查阅访问者模式的资料或咨询专业的编程人员。
设计模式主要分三个类型
设计模式主要分三个类型:创建型、结构型和行为型。
其中创建型有:一、Singleton,单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。
三、Factory Method,工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。
四、Builder,建造模式:将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。
五、Prototype,原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
行为型有:六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
七、Observer,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。
八、Template Method,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。
九、Command,命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
十、State,状态模式:允许对象在其内部状态改变时改变他的行为。
对象看起来似乎改变了他的类。
十一、Strategy,策略模式:定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。
十二、China of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。
[游戏]-游戏开发中常用的设计模式
[游戏]-游戏开发中常⽤的设计模式来源:使⽤设计模式来提⾼程序库的重复利⽤性是⼤型程序项⽬开发必须的。
但是在“四⼈帮”的设计模式概述中提到了23种标准设计模式,不但难以记住,⽽且有些设计模式更多的适⽤于应⽤程序开发,对游戏项⽬引擎设计并没有很多的利⽤价值。
根据经验,精挑细选后,笃志在这⾥记录⼀些⾃认为有利⽤价值的设计模式,以便之后⾃⼰设计时使⽤。
⼀:观察者Observer观察者的设计意图和作⽤是:它将对象与对象之间创建⼀种依赖关系,当其中⼀个对象发⽣变化时,它会将这个变化通知给与其创建关系观察者的设计意图和作⽤是的对象中,实现⾃动化的通知更新。
游戏中观察者的适⽤环境有:游戏中观察者的适⽤环境有1:UI控件管理类。
当我们的GUI控件都使⽤观察者模式后,那么⽤户的任何界⾯相关操作和改变都将会通知其关联对象-----我们的UI事件机。
2:动画管理器。
很多时候我们在播放⼀个动画桢的时候,对其Frame有很⼤兴趣,此时我们设置⼀个FrameLister对象对其进⾏监视,获得我们关⼼的事件进⾏处理是必须的。
观察者伪代码::观察者伪代码// 被观察对象⽬标类Class Subject{// 对本⽬标绑定⼀个观察者 Attach( Observer );// 解除⼀个观察者的绑定 DeleteAttach( Observer );// 本⽬标发⽣改变了,通知所有的观察者,但没有传递改动了什么Notity(){For ( …遍历整个ObserverList …){ pObserver ->Update(); }}// 对观察者暴露的接⼝,让观察者可获得本类有什么变动GetState();}//-------------------------------------------------------------------------------------------------------// 观察者/监听者类Class Observer{// 暴露给对象⽬标类的函数,当监听的对象发⽣了变动,则它会调⽤本函数通知观察者Void Update (){pSubject ->GetState(); // 获取监听对象发⽣了什么变化TODO:DisposeFun(); // 根据状态不同,给予不同的处理}}⾮程序语⾔描述:⾮程序语⾔描述A是B的好朋友,对B的⾏为⾮常关⼼。
JS常用的设计模式(8)——访问者模式
JS常⽤的设计模式(8)——访问者模式GOF官⽅定义:访问者模式是表⽰⼀个作⽤于某个对象结构中的各元素的操作。
它使可以在不改变各元素的类的前提下定义作⽤于这些元素的新操作。
我们在使⽤⼀些操作对不同的对象进⾏处理时,往往会根据不同的对象选择不同的处理⽅法和过程。
在实际的代码过程中,我们可以发现,如果让所有的操作分散到各个对象中,整个系统会变得难以维护和修改。
且增加新的操作通常都要重新编译所有的类。
因此,为了解决这个问题,我们可以将每⼀个类中的相关操作提取出来,包装成⼀个独⽴的对象,这个对象我们就称为访问者(Visitor)。
利⽤访问者,对访问的元素进⾏某些操作时,只需将此对象作为参数传递给当前访问者,然后,访问者会依据被访问者的具体信息,进⾏相关的操作。
据统计,上⾯这段话只有5%的⼈会看到最后⼀句。
那么通俗点讲,访问者模式先把⼀些可复⽤的⾏为抽象到⼀个函数(对象)⾥,这个函数我们就称为访问者(Visitor)。
如果另外⼀些对象要调⽤这个函数,只需要把那些对象当作参数传给这个函数,在js⾥我们经常通过call或者apply的⽅式传递 this对象给⼀个Visitor函数.访问者模式也被称为GOF总结的23种设计模式中最难理解的⼀种。
不过这有很⼤⼀部分原因是因为《设计模式》基于C++和Smalltalk写成.在强类型语⾔中需要通过多次重载来实现访问者的接⼝匹配。
⽽在js这种基于鸭⼦类型的语⾔中,访问者模式⼏乎是原⽣的实现, 所以我们可以利⽤apply和call毫不费⼒的使⽤访问者模式,这⼀⼩节更关⼼的是这种模式的思想以及在js引擎中的实现。
我们先来了解⼀下什么是鸭⼦类型,说个故事:很久以前有个皇帝喜欢听鸭⼦呱呱叫,于是他召集⼤⾂组建⼀个⼀千只鸭⼦的合唱团。
⼤⾂把全国的鸭⼦都抓来了,最后始终还差⼀只。
有天终于来了⼀只⾃告奋勇的鸡,这只鸡说它也会呱呱叫,好吧在这个故事的设定⾥,它确实会呱呱叫。
后来故事的发展很明显,这只鸡混到了鸭⼦的合唱团中。
24种设计模式及案例
24种设计模式及案例设计模式是软件工程中经过验证的解决其中一类常见问题的可复用设计的描述。
它们提供了一套经过验证的最佳实践,可以帮助开发人员解决各种设计问题,并提高代码的可维护性、重用性和灵活性。
本文将介绍24种常见的设计模式,并为每种模式提供一个案例,以便更好地理解和应用这些设计模式。
1.创建型模式:- 简单工厂模式(Simple Factory Pattern):通过一个工厂类根据输入参数的不同来创建不同类的对象。
- 工厂方法模式(Factory Method Pattern):定义一个创建对象的接口,但让子类决定实例化哪一个类。
- 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体的类。
- 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局的访问点来获取该实例。
2.结构型模式:- 适配器模式(Adapter Pattern):将不兼容的接口转换为可兼容的接口,以便不同类之间可以协同工作。
- 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,而不需要修改原始类的代码。
- 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对该对象的访问。
- 外观模式(Facade Pattern):提供了一个简化接口,用于使用一组复杂子系统的更高级别接口。
3.行为型模式:- 策略模式(Strategy Pattern):定义一系列算法,将每个算法封装起来,并使它们可以互相替换。
- 观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,其所有依赖对象都会收到通知并自动更新。
- 模板方法模式(Template Method Pattern):定义了一个操作的算法框架,而将一些步骤的实现延迟到子类中。
23种设计模式
23种设计模式设计模式主要三类型:创建型、结构型⾏型其创建型:⼀、Singleton单例模式:保证类实例并提供访问全局访问点⼆、Abstract Factory抽象⼯⼚:提供创建系列相关或相互依赖象接⼝须指定具体类三、Factory Method⼯⼚:定义⽤于创建象接⼝让类决定实例化哪类Factory Method使类实例化延迟类四、Builder建造模式:复杂象构建与表⽰相离使同构建程创建同表⽰五、Prototype原型模式:⽤原型实例指定创建象种类并且通拷贝些原型创建新象⾏型:六、Iterator迭代器模式:提供顺序访问聚合象各元素需要暴露该象内部表⽰七、Observer观察者模式:定义象间依赖关系象状态发改变所依赖于象都通知⾃更新⼋、Template Method模板:定义操作算⾻架些步骤延迟类TemplateMethod使类改变算结构即重定义该算某些特定步骤九、Command命令模式:请求封装象使⽤同请求客户进⾏参数化请求排队记录请求志及⽀持撤销操作⼗、State状态模式:允许象其内部状态改变改变⾏象看起似乎改变类⼗⼀、Strategy策略模式:定义系列算封装起并使互相替换本模式使算独⽴于使⽤客户⼗⼆、China of Responsibility职责链模式:使象都机处理请求避免请求送发者接收者间耦合关系⼗三、Mediator介者模式:⽤介象封装些列象交互⼗四、Visitor访问者模式:表⽰作⽤于某象结构各元素操作使改变各元素类前提定义作⽤于元素新操作⼗五、Interpreter解释器模式:给定语⾔定义⽂表⽰并定义解释器解释器使⽤该表⽰解释语⾔句⼗六、Memento备忘录模式:破坏象前提捕获象内部状态并该象外保存状态结构型:⼗七、Composite组合模式:象组合树形结构表⽰部整体关系Composite使⽤户单象组合象使⽤具致性⼗⼋、Facade外观模式:系统组接⼝提供致界⾯fa?ade提供⾼层接⼝接⼝使系统更容易使⽤⼗九、Proxy代理模式:其象提供种代理控制象访问⼆⼗、Adapter,适配器模式:类接⼝转换客户希望另外接⼝Adapter模式使原本由于接⼝兼容能起⼯作些类起⼯作⼆⼗⼀、Decrator装饰模式:态给象增加些额外职责增加功能说Decorator模式相⽐类更加灵⼆⼗⼆、Bridge桥模式:抽象部与实现部相离使独⽴变化⼆⼗三、Flyweight享元模式。
网站的几种设计模式
适用性
●当一个类不知道它所必须创建的对象的类的时候。
●当一个类希望由它的子类来指定它所创建的对象的时候。
●当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
二.结构型模式
6.适配器模式 意图
●将一个类的接口ቤተ መጻሕፍቲ ባይዱ换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用性
●你想使用一个已经存在的类,而它的接口不符合你的需求。
●你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
●如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用 Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。
●一个系统需要支持交易(Transaction)。一个交易结构封装了一组数据更新命令。使用命令模式来实现交易结构可以使系统增加新的交易类型。
○虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的 ImageProxy就是这样一种代理的例子。
○保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。例如,在Choices 操作系统[CIRM93]中 KemelProxies 为操作系统对象提供了访问保护。
适用性
●当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
24种设计模式
24种设计模式Factory Pattern(⼯⼚模式):1. 创建对象的接⼝,封装对象的创建;2. 使具体化类的⼯作延迟到⼦类中。
(维护⼀类对象)AbstractFactory Pattern(抽象⼯⼚模型):该模式将⼀组对象的创建封装到⼀个⽤于创建对象的类中。
(解决的问题:要创建⼀组或者相互依赖的对象)。
Singleton Pattern(单例模式):该模式在⾯向纯粹的⾯向对象的范式中⽤于创建唯⼀的实例,值得注意的是Singleton不能被实例化,因此将其构造函数声明为protected或private类型。
Singleton Pattern经常与Factory Pattern结合使⽤,因为Factory对象只能有⼀个。
Builder Pattern(创建者模式):将⼀个复杂的对象的构建与它的表⽰分离,使得同样的构建构成可以创建不同的表⽰。
如建筑师画图纸,⽽⼯⼈建造房屋。
Prototype Pattern(原型模式):提供⼀个通过已存在对象进⾏新对象创建的接⼝(clone)。
(浅拷贝和深拷贝)Bridge Pattern(桥梁模式):将抽象部分与实现部分分开实现,使他们都可以独⽴地变化,并使⽤组合的⽅式将多维度的抽象⽅法联系在⼀起。
⽐如咖啡分⼩杯、中杯、⼤杯以及加奶和不加奶,则抽象部分为:⼩杯、中杯、⼤杯,⾏为为:加奶和不加奶。
Adapter Pattern(适配器模式):适配就是由“源”到“⽬标”的适配,⽽当中链接两者的关系就是适配器。
它负责把“源”过度到“⽬标”。
将⼀个类的接⼝转换成客户希望的另外⼀个接⼝。
Adapter模式使得原本由于接⼝不兼容⽽不能⼀起⼯作的那些类可以⼀起⼯作。
适配器模式分为两种:①⾯向类的设计模式;②⾯向对象的设计模式。
①⾯向类的适配器:该模式使⽤继承和接⼝实现的⽅式复⽤需要适配器的类。
②⾯向对象的适配器:该模式使⽤组合的⽅式实现需要复⽤的类。
Decorator模式(装饰模式):动态地给⼀个对象添加⼀些额外的职责。
26 C#设计模式-访问者模式
访问者模式概述
医院处方单处理示意图
访问者模式概述
分析
处方单: • 药品信息的集合,包含一种或多种不同类型的药品信息
• 不同类型的工作人员(例如划价人员和药房工作人员)在操作 同一个药品信息集合时将提供不同的处理方式
• 可能会增加新类型的工作人员来操作处方单
Design Patterns
访问者模式
刘
伟 (Sunny)
weiliu_china@
大纲
访问者模式概述
访问者模式的结构与实现 访问者模式的应用实例 访问者模式与组合模式联用 访问者模式的优缺点与适用环境
EmployeeList - list : ArrayList = new ArrayList() + AddEmployee (Employee employee) : void + Accept (Department handler) : void ...
Employee + Accept (Department handler) : void ...
访问者模式的结构与实现
访问者模式的结构
Client ConcreteVisitorA + VisitConcreteElementA ( ConcreteElementA elementA) + VisitConcreteElementB ( ConcreteElementB elementB)
软件开发:
• 处方单 • 药品信息 • 工作人员 对象结构 元素 访问者
访问者模式概述
分析
对象结构中存储了多种不同类型的对象信息 对同一对象结构中的元素的操作方式并不唯一,可能 需要提供多种不同的处理方式 还有可能增加新的处理方式
分享一下我记忆23种设计模式的方法
分享⼀下我记忆23种设计模式的⽅法来CNBLOGS好久了,也没写过点什么,最近在学习23种设计模式,既然是要学习这些模式,⾸先得记住吧,呵呵,下⾯我总结我⼀下我的记忆⽅法,希望给⼤家分享。
⾸先列出23种设计模式1 Singleton 单件2 Abstract Factory 抽象⼯⼚模式3 Builder ⽣成器模式4 Factory Method ⼯⼚⽅法模式5 Prototype 原型模式6 Adapter 适配器模式7 Bridge 桥接模式8 Composite 组合模式9 Decorator 装饰模式10 Facade 外观模式11 Flyweight 享元模式12 Proxy 代理模式13 Template Methed模板⽅法14 Command 命令模式15 Interpreter 解释器模式16 Mediator 中介者模式17 Iterator 迭代器模式18 Observer 观察者模式19 Chain Of Responsibility 职责链模式20 Memento 备忘录模式21 State 状态模式22 Strategy 策略模式23 Visitor 访问者模式下⾯我们开始这样记忆根据设计模式前的数字来联想记忆,把1,11,21这样的模式串联起来记忆。
具体如下:1------ 肯定是⼀个了,所以是单个,联想单件模式;11----- 1是最⼩单位,11是由两个1(可以想象成多个1)组成,要解决多个1共享资源的模式是享元模式21----- 由2变成了1.可以想象成⼩弟弟见到MM后由S形变成了棍形,状态发⽣了变化 ---状态模式2------ 把2想象成鸭⼦,是我们的想象,是我们的抽象,想到抽象⼯⼚模式12----- 把我们1家的产品叫给2家或更多家来代理,想到代理模式22----- 从家到公司有2条(或多条)路来⾛(把每个2都想象成弯弯的路),⾛每条都是⼀个策略,策略模式3------ 想象成MM的胸部,⽣成奶汁的地⽅,⽣成器模式13-----⽤印模印过⼩猪吧,这个想象到什么了吗?对!把这个样⼦⾥填充⼀些泥巴,就可以得到MM的mimi模型喽,13象个模板吧?呵呵模板⽅法23-----这个更简单了,两只⼿来摸(访问)MM的mimi,访问者模式4------- 4象⼀⾯⼩红旗,象⼀⾯插在⼯⼚屋顶的⼩红旗,⼯⼚⽅法模式14------ 4象⼀⾯⼩红旗,1⾯红旗就是⼀道命令,命令模式5------- 5象个挺着⼤肚⼦的孕妇,穿再多的⾐服也掩盖不了她这种原型,原型模式15------ 旁边已经有1个⼩孩了,你怎么⼜怀上了?给⼤家解释⼀下吧,解释器模式6-------带天线的电⼦器件,适配器?适配器模式16------我要在淘宝上买⼀个适配器,淘宝就是中介者,中介者模式7-------想象成天桥,桥接模式17------⼀座桥连⼀座桥,桥上还有桥,迭代器模式8------- 8是由oo组合⽽成的组合模式18------- 带着1个望远镜(8象⼀个望远镜)⼲吗?观察呗!观察者模式9------- 象⼀个⽓球,⽓球是⽤来装饰的,装饰模式19------- ⼀串⽓球,每个⽓球都有⾃⼰的位置和职责,职责链模式10------- 瞧,⼀个鸡蛋,鸡蛋的外观就是这样的,外观模式20-------⼀个台灯,⼀个圆桌,我在写备忘录,备忘录模式好了,写到这吧,先每个⼈都有⾃⼰的记忆⽅法,我就是联想,就是瞎想,世界没有联想将会怎样?(另,今天11:10~11:30左右,由于同时链接过多造成⽹站不能访问,当我发布的时候,⽹站不能访问了,苦呀,哭呀,还好,我⼜写了⼀遍)。
数据校验逻辑 java设计模式
数据校验逻辑通常用于验证用户输入的数据是否符合特定的规则或标准。
在Java中,可以使用设计模式来提高代码的可维护性和可复用性。
以下是一些常见的设计模式,可以在数据校验逻辑中应用:
1. 策略模式(Strategy Pattern):策略模式允许根据不同的验证规则动态切换算法。
可以
将不同的验证规则封装为不同的策略类,然后在运行时根据需要选择合适的策略进行数据验证。
2. 访问者模式(Visitor Pattern):访问者模式可以将算法操作与对象结构分离,使得添加
新的验证操作变得容易。
通过定义一个访问者接口,可以添加新的验证逻辑而无需修改已有的类结构。
3. 观察者模式(Observer Pattern):观察者模式允许一个对象(被观察者)自动通知其依
赖对象(观察者)任何状态变更。
在数据校验逻辑中,可以将验证结果作为被观察者的状态变更通知给观察者,以便进行后续处理。
4. 模板方法模式(Template Method Pattern):模板方法模式允许定义一个操作中的算法
骨架,将某些步骤延迟到子类中实现。
在数据校验逻辑中,可以定义一个模板方法,规定数据验证的基本流程,然后由子类实现具体的验证逻辑。
这些设计模式可以帮助您更好地组织代码,提高代码的可维护性和可扩展性。
根据具体的需求和场景,可以选择适合的设计模式来设计数据校验逻辑。
23种设计模式的经典运用
23种设计模式的经典运用介绍设计模式是解决软件设计中常见问题的可重复使用的解决方案。
本文将介绍23种经典的设计模式,并给出它们在实际开发中的应用示例。
通过学习这些设计模式,您将增加对软件设计的理解,并能够更好地解决问题。
创建型设计模式1.工厂方法模式(F a c t o r y M e t h o d)工厂方法模式通过定义一个创建对象的接口,但由子类决定实例化具体类。
这种方法可以延迟实例化过程,具有更高的灵活性和可扩展性。
应用场景:-在一个系统中,希望客户端与具体类的实例化解耦。
-希望通过增加具体类的扩展来增加系统的灵活性。
2.抽象工厂模式(A b s t r a c t F a c t o r y)抽象工厂模式提供一个接口,用于创建相关或依赖对象组。
这种模式将对象的实例化推迟到子类中,从而实现了解耦。
应用场景:-当一个系统独立于其产品的创建、组合和表示时。
-当需要一个系列的相互依赖的对象而无需指定其具体类时。
3.单例模式(S i n gl e t o n)单例模式确保一个类只有一个实例,并提供一个全局访问点。
这种模式常用于控制对资源的访问,例如数据库连接或日志文件。
应用场景:-当需要一个类的唯一实例,并且该实例需要被多个客户端共享时。
-当需要限制系统中特定类的实例数量时。
4.原型模式(P r o to t y p e)原型模式通过复制现有对象来创建新对象。
这种模式对于创建需要消耗大量资源的对象非常有用,可以通过克隆现有对象来提高性能。
应用场景:-当一个系统的某些对象的创建比较昂贵时。
-当需要避免构造函数调用,而直接通过复制现有对象来创建新对象时。
5.建造者模式(B ui l d e r)建造者模式将一个复杂对象的构建过程与其表现分离,使得相同的构建过程可以创建不同的表现。
应用场景:-当想要构建一些复杂对象时,如生成器。
-当需要创建对象的过程具有多个步骤,并且每个步骤都可以按需选择或省略时。
结构型设计模式6.适配器模式(A da p t e r)适配器模式将一个类的接口转换为客户端所期望的另一个接口。
访问者模式的应用场景和实现细节
访问者模式的应用场景和实现细节访问者模式是一种常用的设计模式,在软件开发中经常被使用。
该模式的主要作用是对于一个复杂的软件系统,通过访问者的访问,可以对该系统进行操作和修改,从而实现对系统的扩展和改进。
一、应用场景在实际应用中,访问者模式通常被用在访问和操作一组不同类型的对象时。
例如,在一个图形编辑器中,访问者模式可以被用来实现对于不同类型的图形对象的访问和操作。
具体而言,我们可以定义一个抽象的“访问者”类,该类包括一系列的方法,用于访问和操作图形对象。
然后,每个具体的图形类都可以实现该访问者接口,以便访问者可以对其进行操作。
通过这种方式,我们可以很方便地对图形对象进行扩展和修改。
另一个可以使用访问者模式的场景是在编译器的实现中。
在编译器中,我们可能需要对不同类型的语法树节点进行操作和转换。
访问者模式可以被用来实现对于不同类型的语法树节点的访问和操作,从而使得编译器的实现更加简单和灵活。
二、实现细节在实现访问者模式时,我们需要定义访问者接口和具体的访问者实现。
访问者接口通常包括一系列的方法,用于对不同类型的对象进行访问和操作。
具体而言,访问者接口可能包括如下几个方法:• visitElementA(ElementA elementA): 访问和操作类型为ElementA的对象• visitElementB(ElementB elementB): 访问和操作类型为ElementB的对象• visitE lementC(ElementC elementC): 访问和操作类型为ElementC的对象在访问者接口中,为每一种可能的对象类型都定义了一个对应的visit方法。
对于每个具体的访问者实现,需要根据其需求来实现这些visit方法。
例如,在图形编辑器中,我们可能需要实现如下的一些visit方法:• visitCircle(Circle circle): 访问和操作圆形对象• visitRectangle(Rectangle rectangle): 访问和操作矩形对象• visitLine(Lin e line): 访问和操作直线对象通过实现这些visit方法,我们就可以访问和操作不同类型的图形对象。
设计模式之——visitor模式
设计模式之——visitor模式visitor模式,⼜叫访问者模式,把结构和数据分开,编写⼀个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类。
这样,当需要增加新的处理时候,只需要编写新的访问者类,让数据结构可以接受访问者的访问即可。
本次,我们以电脑装机为例。
需求是,想组装⼀台电脑,有三个硬件,显卡,CPU和硬盘,想装进电脑主机箱⾥⾯,只能采取接⼝的⽅式。
⾸先我们假设使⽤的是usb接⼝去连接。
下⾯是具体的代码:因为要表现出接⼝可换的概念,我采⽤的是将电脑硬件和电脑本⾝的类以及接⼝的interface接⼝类放到⼀个包⾥⾯,设定这个包为框架包,是不允许修改的。
在框架包中ComputerPart硬件的⽗类,抽象类package site.wangxin520.gof.visitor.framework;/*** 电脑的零配件的⽗抽象类* @author wangXgnaw**/public abstract class ComputerPart {/*** 所有的零配件,都必须通过⼀个硬件接⼝进⾏连接* @param hardwareInterface*/protected abstract void link(HardwareInterface hardwareInterface);}硬件的实现类CPU,下同package site.wangxin520.gof.visitor.framework;/*** 电脑的硬件CPU,⽤于数据的运算** @author wangXgnaw**/public class CPU extends ComputerPart {@Overrideprotected void link(HardwareInterface hardwareInterface) {// 先得通过接⼝连接数据hardwareInterface.visitor(this);// 连接完了之后,就开始使⽤cpuSystem.out.println("连接上了之后,利⽤cpu进⾏计算数据");}}显卡VideoCardpackage site.wangxin520.gof.visitor.framework;/*** 电脑硬件之显卡通过显卡可以进⾏电脑的屏幕图像的显⽰** @author wangXgnaw**/public class VideoCard extends ComputerPart {@Overrideprotected void link(HardwareInterface hardwareInterface) {// 必须先⽤接⼝连接上显卡hardwareInterface.visitor(this);System.out.println("连接上显卡之后,显卡开始⼯作,提供图像");}}硬盘HardDiskpackage site.wangxin520.gof.visitor.framework;/*** 电脑硬件之硬盘** @author wangXgnaw**/public class HardDisk extends ComputerPart {@Overrideprotected void link(HardwareInterface hardwareInterface) {// 必须先通过接⼝,把硬盘先连上,然后才能操作hardwareInterface.visitor(this);// 硬盘开始⼲活System.out.println("硬盘以及连接上了,开始存储数据");}}Computer,电脑(主机箱)类package site.wangxin520.gof.visitor.framework;/*** 电脑的类,当需要装机的话,就先准备好硬件,即new出来,然后插上接⼝* @author wangXgnaw**/public class Computer {/*** 想装机,先得提供硬件接⼝才⾏* @param hardwareInterface*/public void useComputer(HardwareInterface hardwareInterface){//通过接⼝,连接cpunew CPU().link(hardwareInterface);//通过接⼝,连接显卡new VideoCard().link(hardwareInterface);//通过接⼝连接硬盘new HardDisk().link(hardwareInterface);}}硬件的接⼝类package site.wangxin520.gof.visitor.framework;/*** 硬件的接⼝* @author wangXgnaw**/public interface HardwareInterface {//定义了⼀些接⼝,访问硬件⽤的public void visitor(CPU cpu);public void visitor(VideoCard vCard);public void visitor(HardDisk hd);}把上⾯的框架包封装起来,因为访问者模式要求,结构不能变化,只能变化数据操作上。
php高级面试题
php高级面试题在准备面试和寻求PHP高级开发岗位时,对于一些常见的PHP高级面试题的准备非常重要。
通过了解和掌握这些面试题,你将能更好地展示自己的技能和知识,从而有更大的机会获得理想的职位。
下面,我将介绍一些常见的PHP高级面试题。
一、面向对象编程(Object-Oriented Programming, OOP)1. 请解释面向对象编程的概念和优势。
面向对象编程是一种程序设计范例,它将相关的数据和操作封装在对象中,并通过对象之间的交互实现程序逻辑。
与传统的过程式编程相比,面向对象编程具有更好的可维护性、可扩展性和代码重用性。
2. 请解释面向对象编程中的封装、继承和多态。
封装是指将相关的数据和操作封装在一个对象中,对外部隐藏对象的内部细节,只通过公共接口与对象进行交互。
继承是指通过继承机制,可以基于已有的类创建新的类,并且新的类可以继承并重用父类的属性和方法。
多态是指一个对象可以在不同的上下文中表现出不同的行为。
通过接口和抽象类的使用,可以实现多态性。
3. 请解释什么是接口和抽象类。
接口是一种规范,定义了一个类应该实现的方法。
它只包含方法的声明,没有实现的具体代码。
类可以实现一个或多个接口,从而拥有接口中定义的方法。
抽象类是一个不能被实例化的类,只能被继承。
它可以包含抽象方法和具体方法。
抽象方法只有声明,没有实现,需要在继承的子类中实现。
二、设计模式(Design Patterns)1. 请列举几种常见的设计模式,并解释它们的应用场景。
- 工厂模式(Factory Pattern):用于创建对象的模式,将对象的创建过程封装在工厂类中,客户端通过工厂类获取所需的对象。
- 单例模式(Singleton Pattern):确保一个类只有一个实例对象,并提供全局访问点。
- 观察者模式(Observer Pattern):定义对象之间一对多的依赖关系,当一个对象状态改变时,其所有依赖都会收到通知。
- 访问者模式(Visitor Pattern):将对象结构与操作分离,使得操作可以独立变化,而不影响结构。
JAVA访问者模式
访问者模式(Visitor)Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循一定的编程模式,才能使自己的代码便于理解,易于交流,Visitor(访问者)模式是比较常用的一个模式.应用场景:对于某对象结构中各元素的操作。
如果需要在不修改各元素类的前提下定义作用于这些元素的新操作,也就是动态的增加新的方法应该考虑访问者模式。
想让数个不同的访问者对同一个对象集合进行访问时,Visitor模式可以发挥它的强大作用。
Visitor先调用了Visitable 类中的方法,这个方法又回调到Visitor类中在此写了10个java类来描述说明Visitor设计模式;1、NodeA.java 可访问节点A2、NodeB.java 可访问节点B3、NodeC.java 可访问节点C4、Visitable.java 可访问对象接口5、Visitor.java 访问者接口6、VisitorA.java 访问者A7、VisitorTest.java 带有main方法的测试类5变体、Visitor.java 访问者接口(应用java反射机制)6变体、VisitorA.java 访问者A(应用java反射机制)7变体、VisitorTest.java 带有main方法的测试类(应用java反射机制)=============== 1、NodeA.javapackage visitor;public class NodeA implements Visitable {public void accept(Visitor visitor) {visitor.visit(this);}}=============== 1 end=============== 2、NodeB.javapackage visitor;public class NodeB implements Visitable {public void accept(Visitor visitor) {visitor.visit(this);}}=============== 2 end=============== 3、NodeC.java package visitor;public class NodeC implements Visitable { public void accept(Visitor visitor) {visitor.visit(this);}}=============== 3 end=============== 4、Visitable.java package visitor;public interface Visitable {public void accept(Visitor visitor);}=============== 4 end=============== 5、Visitor.java package visitor;import java.util.Collection;public interface Visitor {//访问节点Apublic void visit(NodeA nodeA);//访问节点Bpublic void visit(NodeB nodeB);//访问节点Cpublic void visit(NodeC nodeC);//访问节点集合public void visitCollection(Collection collection);}=============== 5 end=============== 6、VisitorA.javapackage visitor;import java.util.Collection;import java.util.Iterator;public class VisitorA implements Visitor {public void visit(NodeA a){System.out.println("Execute visitNodeA method!");; }public void visit(NodeB b){System.out.println("Execute visitNodeB method!");; }public void visit(NodeC c){System.out.println("Execute visitNodeC method!");; }public void visitCollection(Collection collection){Iterator iterator = collection.iterator();while (iterator.hasNext()) {Object o = iterator.next();if (o instanceof Visitable)((Visitable)o).accept(this);}}}=============== 6 end=============== 7、VisitorTest.javapackage visitor;import java.util.ArrayList;import java.util.List;public class VisitorTest {public static void main(String[] args) {NodeA nodeA = new NodeA();NodeB nodeB = new NodeB();NodeC nodeC = new NodeC();VisitorTest nodeD = new VisitorTest();//访问单个对象VisitorA visitorA = new VisitorA();visitorA.visit(nodeA);visitorA.visit(nodeB);visitorA.visit(nodeC);//访问集合List<Visitable> list = new ArrayList<Visitable>();list.add(nodeA);list.add(nodeB);list.add(nodeC);visitorA.visitCollection(list);}}=============== 7 end在两个接口Visitor和Visitable中,确保Visitable很少变化,也就是说,确保不能老有新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.当然采用java反射机制, 可以使对象集合中的对象经常有变化。
简说设计模式——访问者模式
简说设计模式——访问者模式⼀、什么是访问者模式 访问者模式是⼀个相对⽐较简单,但结构⼜稍显复杂的模式,它讲的是表⽰⼀个作⽤于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作⽤于这些元素的新操作。
例如,你在朋友家做客,你是访问者,朋友接收你的访问,你通过朋友的描述,然后对朋友的描述做出⼀个判断,这就是访问者模式。
访问者模式(Visitor ),封装⼀些作⽤于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作⽤于这些元素的新的操作。
UML结构图如下: 其中,Visitor 是抽象访问者,为该对象结构中ConcreteElement 的每⼀个类声明⼀个Visit 操作;ConcreteVisitor 是具体访问者,实现每个由visitor 声明的操作,是每个操作实现算法的⼀部分,⽽该算法⽚段是对应于结构中对象的类;ObjectStructure 为能枚举它的元素,可以提供⼀个⾼层的接⼝以允许访问者访问它的元素;Element 定义了⼀个Accept 操作,它以⼀个访问者为参数;ConcreteElement 为具体元素,实现Accept 操作。
1. 抽象访问者 此处可为抽象类或接⼝,⽤于声明访问者可以访问哪些元素,具体到程序中就是visit ⽅法的参数定义哪些对象是可以被访问的。
2. 具体访问者 影响访问者访问到⼀个类后该⼲什么、怎么⼲。
这⾥以ConcreteVisitor1为例,ConcreteVisitor2就不再赘述了。
1 public abstract class Visitor {23 public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);45 public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);67 } 1 public class ConcreteVisitor1 extends Visitor {23 @Override4 public void visitConcreteElementA(ConcreteElementA concreteElementA) {5 System.out.println(concreteElementA.getClass().getName() + " 被 " + this .getClass().getName() + " 访问");6 }78 @Override9 public void visitConcreteElementB(ConcreteElementB concreteElementB) {10 System.out.println(concreteElementB.getClass().getName() + " 被 " + this .getClass().getName() + " 访问");11 }1213 } 3. 抽象元素 此处为接⼝后抽象类,⽤于声明接受哪⼀类访问者访问,程序上是通过accpet⽅法中的参数来定义的。
Visitor Design Pattern
Visitor Design Pattern访问者设计模式访问者是一种行为型设计模式,它允许你在无需修改其它对象的情况下为对象添加新功能。
当你需要在多个不同对象中执行同一操作时,使用访问者可以将这些操作从对象中解耦出来,从而使代码更加模块化和易于维护。
设计模式是一种可复用的解决方案,旨在解决在特定情境中重复的问题。
设计模式有很多种,每种模式都有其特定的场景和优缺点。
在这些模式中,访问者模式是一种比较常见和灵活的模式。
下面我们来探讨一下访问者模式的实现和应用。
1. 模式定义访问者模式指的是在不改变数据结构的前提下,定义作用于该结构中的各个元素的新操作。
访问者模式的目的是将算法与对象结构分离。
在实际应用中,一般将访问者模式分为两个部分:访问者和被访问的对象。
2. 模式结构访问者模式有访问者和被访问者两个核心组成部分,其中访问者负责对对象进行不同的操作,而被访问者负责提供访问者所需操作的基本数据。
在访问者模式中,被访问者一般由一个抽象类和其子类组成。
被访问者抽象类中定义了被访问者需要支持的元素和接口,各个子类则实现了该抽象类的接口,代表不同的被访问者。
在访问者模式中,访问者一般由一个抽象类和其子类组成。
访问者抽象类中定义了访问者需要支持的操作和接口,各个子类则实现了该抽象类的接口,代表不同的访问者。
3. 模式应用访问者模式可以应用于以下场景:(1)当需要在对象结构中添加新的操作而不改变其原有结构时,可以使用访问者模式。
由于访问者模式可以将算法与数据结构分离,从而使得算法不会对数据结构造成任何影响。
(2)当对象的结构比较稳定,但是需要在该结构上频繁增加新的操作时,可以使用访问者模式。
使用这种模式可以减少因操作变化而导致的影响,并且不会影响到原有的数据结构。
(3)当一组对象中包含多个不同的类,并且需要对这些对象进行相同的操作时,可以使用访问者模式。
在这种情况下,访问者模式可以将多个不同的对象转化为一个访问接口,从而方便对这些对象进行处理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Visitor - 访问者模式话说有一个银行,有三个窗口,但是每个窗口的智能都是一样的,即都能办理所有的业务。
因此每位来银行办理业务的人只要排队就是了,排到你了,就向业务员说明你要办理的业务,然后业务员根据你的业务选择不同的单据,打开不同的账本。
……。
业务员此时典型的工作流程是:Java代码1if (service instanceof Saving){2//存款3 ......4}else if (service instanceof Draw){5//提款6 ......7}else if (service instanceof Fund){8//基金9 ......10}11......于是每位业务员的桌面总是塞得满满的,更重要的是大量的时间都花在受理不同业务之间的切换,使得效率很低。
有没有方法能够使得业务员的工作效率提高呢?银行经理苦思冥想了半天,终于想出了一个好办法。
他让每个窗口各负责一个业务,同时委任了一位访问者(Visitor),负责在客户进门时,询问他要办理什么业务,告诉他应该去哪个窗口办理。
这样,每个窗口的业务员就只负责一项业务,减少了在不同业务间切换的时间耗费,效率大大提高。
更重要的是,当某一项业务的处理流程发生变更时,不需要同时麻烦三个窗口的业务员,而只需要让处理这项业务的业务员进行修改就可以了。
下面就来定义Visitor类,这个Visitor类实际上还办含了不同窗口受理员的职责,可以认为是银行的受理反应机制吧。
Java代码12public class Visitor {1314public void process(Service service){ 15// 默认业务16}1718public void process(Saving service){ 19// 存款20}2122public void process(Draw service){23// 提款24}2526public void process(Fund service){27// 基金28}29}接着我们定义业务基类。
Java代码30public class Service {31public void accept(Visitor visitor) {32visitor.process(this);33}34}不同的业务类。
Java代码35public class Saving extends Service {36//各种业务处理流程37}Java代码38public class Draw extends Service {39//各种业务处理流程40}Java代码41public class fund extends Service {42//各种业务处理流程43}好了,接下来就是我们的访问者与到来的客户之间的交互了。
Java代码44public class Client {45public static void main(String[] args) {46Service s1 = new Saving();47Service s2 = new Draw();48Service s3 = new Fund();4950Visitor visitor = new Visitor();5152s1.accept(visitor);53s2.accept(visitor);54s3.accept(visitor);55}56}后话:专门设定一个访问者的职位还是有点多余,于是后来银行经理请设备公司做了一个排号机来代替访问者。
总结Visitor模式实际上是利用的语言本身的特性,见Vistor类的各个函数,通过不同的参数来自动查找相应的处理函数。
采用Visitor的好处如上面说到的那样,当需要改变其中一项业务的处理时,不需要每个地方都进行修改,而只需要改动Visitor类中相应的处理函数就可以了。
也就是说它适合于业务处理时常发生变动的情况。
当然,Visitor也有它自身的限制。
它不适合于业务数量的经常变化,因为一旦新增或删除一些Service时,需要对visitor进行相应的增删。
也就是说具体Service与Visitor是耦合的。
wangdi 写道引用当然,Visitor也有它自身的限制。
它不适合于业务数量的经常变化,因为一旦新增或删除一些Service时,需要对visitor进行相应的增删。
也就是说具体Service与Visitor是耦合的。
其实,我非常想知道关于visitor模式的定义,,有了准确定义,实现应该会比较简单。
注:我这儿的accept()、process()方法和lz的对应的方法是不一样的。
Java代码1public interface IVisitor {2public void accept(IService service);3}Java代码4public interface IService {5public void process(IVisitor vistor);6}Java代码7public class Fund implements IService {8public void process(IVisitor vistor){9System.out.println("处理" + this);10}1112public String toString(){13return"基金业务";14}15}Java代码16public class Saving implements IService {17public void process(IVisitor vistor) {18System.out.println("处理" + this);19}2021public String toString() {22return"存款业务";23}24}Java代码25public class Visitor implements IVisitor {26public void accept(IService service) {27service.process(this);28}29}Java代码30public class VisitorClients0 {31public static void main(String[] args) {32IVisitor visitor = new Visitor();3334IService fundService = new Fund();35IService savingService = new Saving();3637visitor.accept(fundService);38visitor.accept(savingService);39}40}网上关于访问者大多数定义都像楼主所举的。
但是访问者模式,重点是不改变原有的类与类继承关系上,为原有的类体系增加新的功能这是类图.由于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的AOP4 题化话------ 访问者名字的由来。
也许是Element的各个子类---------为来访的客人预留下了座位。
来访客人每次带一大包实用的礼物,让Element的子类的实例增加自已的魔法功能。
来访的客人各不相同,带来的礼物五花八门,于是Element的子类的实例,展现出魔术般的神奇效果。
======================================================以上是三年前对vitor的个人理解。
尘封了N久的记忆,总算被打开了。
说事在的,二十三种模式,仅有少数几种留下了深刻的印像,其余的都淡忘掉了。
唯独模式设计的封装变化点在心中。
好在,还有自已能看懂的笔记一直保存着。
Visitor模式的使用情景以及与Iterator的比较见我以前的一篇文章/blog/166142这次主要讨论Visitor的两种实现方式及其优劣。