访问者模式允许在不扩展对象类的情况下编写对象上的操作.当然.但是为什么不编写一个从外部操作我的对象集合的全局函数或静态类呢?基本上,在像 java这样的语言中,出于技术原因需要accept()方法;但是在一种我可以在没有accept()方法的情况下实现相同设计的语言中,访问者模式是否变得微不足道?

说明:在访问者模式中,可访问的类(实体)有一个方法.accept(),其作用是调用访问者的.visit()方法.我可以看到java示例的逻辑:访问者为它支持的每个可访问类型定义了一个不同的.visit(n)方法,并且必须使用.accept()技巧在运行时选择它们.但是像python或PHP这样的语言有动态类型,没有方法重载.如果我是访问者,我可以在不知道实体的类型甚至方法的完整签名的情况下调用实体方法(例如.serialize()). (这是“双重调度”问题,对吧?)

我知道一个接受方法可以将受保护的数据传递给访问者,但有什么意义呢?如果数据公开给访问者类,它实际上是类接口的一部分,因为它的详细信息在类之外很重要.无论如何,公开私人数据从来没有让我感到自己是访客模式的重点.

因此,似乎在python,ruby或PHP中我可以在访问对象中没有接受方法(并且没有反射)的情况下实现类似访问者的类,对吧?如果我可以使用一系列异构对象并在没有“访问”类的任何合作的情况下调用他们的公共方法,那么这仍然应该被称为“访问者模式”吗?是否存在我缺失的模式的本质,或者它是否只是归结为“编写一个从外部操作对象来执行操作的新类”?

PS.我已经看过很多关于SO和其他地方的讨论,但找不到任何解决这个问题的东西.指针欢迎.

这个答案是在忽略 PHP等的情况下做出的,但访问者通常需要调用的不仅仅是实体上的单个方法(您提到“序列化”).当在具体的访问者上调用Visit()方法时,访问者能够为每个实体子类型运行不同的代码.我不知道这与动态类型的语言有什么不同(虽然我喜欢一些反馈).

Visitor的另一个好处是它提供了一个干净的分离代码,它可以从枚举实体的代码中运行每个实体.这在至少一个大型项目中为我节省了一些严重的代码重复.

顺便说一句,我在没有方法重载的语言中使用了Visitor.您只需使用VisitN(TypeN n)替换Visit(TypeN n).

跟进评论.

这是访问者伪造的代码,如果没有访问对象的合作(至少没有切换块),我不知道如何这样做:

abstract class ScriptCommand
{
   void Accept(Visitor v);
}

abstract class MoveFileCommand
{
   string TargetFile;
   string DestinationLocation;

   void Accept(Visitor v)
   {
      v.VisitMoveFileCmd(this);  // this line is important because it eliminates the switch on object type
   }
}

abstract class DeleteFileCommand
{
   string TargetFile;

   void Accept(Visitor v)
   {
      v.VisitDeleteFileCmd(this); // this line is important because it eliminates the switch on object type

   }
}

// etc,many more commands

abstract class CommandVisitor
{
   void VisitMoveFileCmd(MoveFileCommand cmd);
   void VisitDeleteFileCmd(DeleteFileCommand cmd);
   // etc
}

// concrete implementation

class PersistCommandVisitor() inherits CommandVisitor
{
   void VisitMoveFileCmd(MoveFileCommand cmd)
   {
      // save the MoveFileCommand instance to a file stream or xml doc
      // this code is type-specific because each cmd subtype has vastly
      // different properties
   }

   void VisitDeleteFileCmd(DeleteFileCommand cmd)
   { 
      // save the DeleteFileCommand instance to a file stream or xml doc
      // this code is type-specific because each cmd subtype has vastly
      // different properties
   }

}

访问者基础结构允许处理各种命令子类型,没有选择案例,swithc,if else.

对于处理枚举的访问者,我认为你是这样限制自己的.这并不是说合作类(抽象的VisitorEnumerator)不能参与其中.

例如,请注意此访问者不知道枚举的顺序:

class FindTextCommandVisitor() inherits CommandVisitor
{
   string TextToFind;
   boolean TextFound = false;

   void VisitMoveFileCmd(MoveFileCommand cmd)
   {
      if (cmd.TargetFile.Contains(TextToFind) Or cmd.DestinationLocation.Contains(TextToFind))
         TextFound = true;
   }


   void VisitDeleteFileCmd(DeleteFileCommand cmd)
   { 
      // search DeleteFileCommand's properties
   }

}

这允许它像这样重复使用:

ScriptCommand FindTextFromTop(string txt)
{
   FindTextCommandVisitor v = new FindTextCommandVisitor();
   v.TextToFind = txt;
   for (int cmdNdx = 0; cmdNdx < CommandList.Length; cmdNdx++)
   {
      CommandList[cmdNdx].Accept(v);
      if (v.TextFound)
         return CommandList[cmdNdx];  // return the first item matching
   }
}

并列举与同一访客相反的方式:

ScriptCommand FindTextFromBottom(string txt)
{
   FindTextCommandVisitor v = new FindTextCommandVisitor();
   v.TextToFind = txt;
   for (int cmdNdx = CommandList.Length-1; cmdNdx >= 0; cmdNdx--)
   {
      CommandList[cmdNdx].Accept(v);
      if (v.TextFound)
         return CommandList[cmdNdx];  // return the first item matching
   }
}

在实际代码中,我将为枚举器创建一个基类,然后将其子类化以处理不同的枚举场景,同时传递具体的Visitor子类以完全解耦它们.希望你能看到保持枚举分离的力量.

php – 访问者模式对动态类型语言有用吗?的更多相关文章

  1. Swift设计模式之访问者模式

    转自Swift设计模式原文Design-Patterns-In-Swift

  2. Swift是动态还是静态语言?

    我只是好奇,如果Swift是动态的像PHP或静态,我的意思是我可以在应用程序运行时生成类?

  3. android – 以编程方式更改R.String的值

    你能在android程序中以编程方式更改R.string的值吗?,但似乎只涉及改变语言,他最终以不同的方式做到了.有人可以伸出援助之手吗?

  4. 浅谈PHP面向对象之访问者模式+组合模式

    下面小编就为大家带来一篇浅谈PHP面向对象之访问者模式+组合模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. java访问者模式的静态动态及伪动态分派彻底理解

    这篇文章主要为大家介绍了java访问者模式的静态动态及伪动态分派彻底理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  6. 轻松掌握php设计模式之访问者模式

    这篇文章主要帮助大家轻松掌握php设计模式之访问者模式,感兴趣的小伙伴们可以参考一下

  7. Html5在手机端调用相机的方法实现

    这篇文章主要介绍了Html5在手机端调用相机的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. Groovy动态语言使用教程简介

    这篇文章主要为大家介绍了Groovy动态语言使用教程简介,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  9. ubuntu – stunnel:SSL到SSL? (对于smtp / imap)

    如何配置stunnel以进行SSL连接,然后再连接到其他服务器上的SSL端口?UbuntuServer10.10的具体步骤是什么?

  10. PHP file_get_contents()的行为与浏览器不同

    我正在尝试使用PHP下载网页的内容.当我发出命令时:它返回一个报告服务器已关闭的页面.然而,当我将相同的URL粘贴到我的浏览器中时,我得到了预期的页面.有谁知道是什么导致了这个?file_get_contents是否会传输任何区别于浏览器请求的标头?

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部