设计师设计模式与访客设计模式的区别

问题描述:

我相信了解设计师模式与访客设计模式的意图。设计师设计模式与访客设计模式的区别

虽然我可以列出下列差别

  1. 装饰工程的对象上,访问者适用于复合结构,
  2. 装饰是结构设计图案,访客是行为的设计模式。

当我深思下去时,我无法说服自己两者之间的真正区别是什么。

那么,他们实际上是不同的,因为他们可以!

使用修饰器当你想用一些新的,或多或少的透明功能如验证或缓存来增强现有对象时。看到这里例如:Should I extend ArrayList to add attributes that isn't null?

,另一方面游客当你有一个类的层次结构,并要根据具体类型,但避免instanceoftypeof运营商运行不同的方法使用。见活生生的例子:Is This Use of the "instanceof" Operator Considered Bad Design?

装饰工程的对象上,参观者适用于复合材料结构,

游客作品在继承层次,复合是一个不同的GoF设计模式。

装饰是结构设计模式,访客是行为设计​​模式。

确实如此,但它并不能真正帮助理解它们的工作原理吗?

设计模式并不意味着在实现差异但什么时候应该使用一种或另一种分类。

它们用于完全不同的目的:

  • ,当你想通过提供装饰其他对象单一元素动态充实对象的功能,使它们真正添加一些行为,他们(你会用装饰实际上它是在这个意义上结构模式,它改变了你与沃金
  • 当你想一个算法从它使用的对象分开,你会使用访问者的对象)的结构。你所做的是你有这个访问者被传递给多个不同的对象,通常是一个层次结构(他们被称为接受访问者),这个访问者根据它正在访问的对象的类型具体的时刻。通过这种方式,您可以让访问者根据特定对象做任何事情,而无需在对象本身中指定这些操作(这就是为什么它是行为)。这是一种抽象方法,没有在对象本身中定义。

我喜欢认为装饰器允许避免继承,然后扩展类,因为尽管你以某种方式继承,但OOP的一般原则是偏好聚合而非继承。这里是一个过于简单的例子

abstract class Chef{ 
    public abstract void Prepare(); 
} 

class CookieMaker:Chef{   //Concrete class 
    public override void Prepare() 
    { 
     //Bake in Oven 
    } 
} 

    // Decorator class 
// This chef adds chocolate topping to everything 
class ChocoChef:Chef{ 

    public ChocoChef(Chef mychef) 
    { 
     this.chef = mychef; 
    } 

    public override void Prepare() 
    { 
      // Add chocolate topping first 
      chef.Prepare() 
    } 
} 

我为了空间的缘故缩短了一些细节。例如,你可以抽出一名厨师,添加任何种类的顶部,然后ChocoChef成为其具体的类。现在,无论您准备什么,ChocoChef都会添加巧克力配料。所以现在你可以通过将相应的厨师传递给它的构造者来获得巧克力饼干或巧克力蛋糕。另一方面,访问者对对象起作用,并决定根据访问对象做些事情。

class Student{ 
    // Different visitors visit each student object using this method 
    // like prize distributor or uniform inspector 
    public Accept(IVisitor v) 
    { 
     v.Visit(this) 
    } 
} 

// Visitor visits all student OBJECTS 
class PrizeDistributor:IVisitor{ 
    public override void Visit(Student s) 
    { 
      // if(s has scored 100) 
      // Award prize to s 
    } 
} 

我解释的方式,参观者表示,我们可能要采取或物体的动作,但不一定是固有的对象,并且是关系,而水平。例如,我可以为一辆汽车“做一个营销宣传”,但我不会为汽车对象设计一个“createMarketingPitch”功能,因为这对于在我的汽车对象上创建许多功能将是一个滑坡。

另一方面,装饰器是一种模式,它在现有对象之上分层功能,垂直关系用于修改对象在调用正常功能时的行为方式。此外,虽然访问者被编码为使用一类对象,但可将装饰者分配给对象的特定实例,以便相同类型的不同实例的行为不同于彼此。

+0

+1为了描述“水平关系”的访问者模式,这有助于我可视化何时以及为什么使用它。 – ryanp102694 2017-04-26 09:26:57

它们都将“添加功能”添加到现有对象,而无需修改原始类。所不同的是:

随着装饰你加一个包装,这个对象具有基本功能的功能(例如,除了执行一些基本的动作也将其写入日志,除了将文件写入到磁盘中也对其进行加密) 。这也允许我们创建不同的装饰器组合,而不需要为每个可能的场景划分子类。

与顾客你加你不想定义为基本组件类本身(甚至还不如一个包装基本功能),例如由于单一职责原则,开放的一部分,一个完全新的行为关闭原则等。 当相同类型的不同子类之间的行为不同时(如果没有任何复杂的子类结构但只有一个类可以创建一个新类并通过构图包含原始类,并且仍然达到不影响或修改原始类别的目标)。这样你就可以避免编写像if (a is ConcreteClass1) {...} else if (a is ConcreterClass2) {...}这样的代码,而无需编写虚拟方法。

由于这种差异,使用装饰器,客户端代码调用基本组件类的接口上定义的相同方法,现在它只是“装饰”了额外的功能,而客户端调用一些常规“接受”方法并向其发送访问者。

我想装饰模式的方式是当我想在运行时添加功能的对象。在程序运行时,我可以通过将对象包装到可以扩展其方法的装饰器类中将对象添加到对象中。

对于访问者模式,我喜欢它,当我必须对同一类型的“一组”对象进行操作并收集信息时。比方说,我有10个具体的蔬菜类,我想知道所有10个蔬菜的总价。我可以使用访客模式来“访问”每个蔬菜对象,并且在迭代结束时我会有总价。当然,您也可以使用该模式作为将某个操作与对象分离的一种方式。

Decorator

装饰图案可以被用来静态延伸(装饰)的某个对象的功能,或在某些情况下在运行时,独立地是相同类的其他实例的,提供了一些基础工作在设计时完成

何时使用装饰模式?

  1. 对象职责和行为应该是动态添加/移除
  2. 混凝土实现应该从责任去耦和行为
  3. 当子 - 分级过于昂贵动态地添加/删除责任

相关文章:

When to Use the Decorator Pattern?

Visitor

访问者设计模式是从在其它操作对象结构分离的算法的方法。这种分离的实际结果是能够在不修改这些结构的情况下向现有对象结构添加新的操作。这是遵循开放/封闭原则的一种方式。

何时使用访客模式?

  1. 类似的操作都必须在一个结构
  2. 您需要执行很多不同的和无关的业务组合不同类型的对象进行的。它从物体结构分离操作
  3. 新业务有没有对象结构的变化将被添加
  4. 收集相关操作成一个类,而不是强迫你改变或派生的类
  5. 添加功能的类库,你要么没有来源或不能更改源

相关岗位:

When should I use the Visitor Design Pattern?

相关链接:

sourcemaking装饰条

oodesign游客文章

sourcemaking游客文章

是的,他们都添加一些功能,在运行时的现有系统,并尽量少一些被动反应(在一个很好的意义上)动态变化,但有一些差异。

访问者主要是为了尊重OCP(有时是SRP),以使系统更加灵活。随着程序的发展,您可以添加任何访问者,而无需更改现有系统。但是,您需要以事先设定系统。你不能为已经运行的系统添加一个新的Visitor类(或模式),并期望它不用重新编译,重新测试或者任何其他的工作。另一方面,您可以使用装饰器通过将抽象基类(您已有的)包装到装饰器中来丰富现有系统的功能,并将您丰富的特性作为单独的对象提供,以便您可以您可以根据需要进行创建。而且,在语义上,装饰者相当于指出某物的出现。

哪一个更喜欢?海事组织,回答这可能会更有帮助。对我而言,我不喜欢装饰者使用基类的方式。它都使用继承和聚合。如果您需要更改此类(wrapee),则最终将重新编译整个层次结构/模块。但它很方便,您可以在设计时间后更改行为。另一方面,在Visitor模式中,我不喜欢在Visitor实现中了解每个具体类型的想法。当你添加一个新的基类类型时,你也需要去改变Visitor类来添加它。但是,当您需要代码注入到现有系统而不改变结构或您需要分离课程中的问题(单用户响应)时,此功能很有用。

最后,什么让Visitor比普通继承更好?依靠。使用继承你将更加依赖于接口签名。使用访问者使您的访问者类依赖于具体的类。更不用提你在不改变现有模块签名的情况下使用访问者添加更多行为,而不是在现有类中实现新的接口。