Design patterns 装饰设计模式与访客设计模式的区别

Design patterns 装饰设计模式与访客设计模式的区别,design-patterns,decorator,visitor,Design Patterns,Decorator,Visitor,我相信能够理解设计师和访客设计模式的意图 尽管我可以列出以下区别 装饰者处理对象,访客处理复合结构 装饰者是结构设计模式,访客是行为设计模式 当我深入思考时,我无法说服自己这两者之间的真正区别是什么。好吧,它们实际上是尽可能不同的 当您想用一些新的、或多或少透明的功能(如验证或缓存)来增强现有对象时,可以使用Decorator。请参见此处的示例: 另一方面,当您有一个类的层次结构,并且希望根据具体类型运行不同的方法,但避免使用instanceof或typeof运算符时,可以使用Visitor。请

我相信能够理解设计师和访客设计模式的意图

尽管我可以列出以下区别

  • 装饰者处理对象,访客处理复合结构
  • 装饰者是结构设计模式,访客是行为设计模式

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

    好吧,它们实际上是尽可能不同的

    当您想用一些新的、或多或少透明的功能(如验证或缓存)来增强现有对象时,可以使用Decorator。请参见此处的示例:

    另一方面,当您有一个类的层次结构,并且希望根据具体类型运行不同的方法,但避免使用
    instanceof
    typeof
    运算符时,可以使用Visitor。请参阅真实示例:

    装饰者处理对象,访客处理复合结构

    Visitor使用继承层次结构,Composite是一种不同的GoF设计模式

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

    是的,但这对理解它们是如何工作的没有帮助

    另见

    设计模式不是按实现差异来分类的,而是按应该何时使用一种或另一种来分类的

    它们的用途完全不同:

    • 当您希望通过提供装饰其他对象的单个元素来动态丰富对象的功能时,您将使用decorator,以使它们实际添加一些行为(实际上,它是一种结构模式,可以改变您正在使用的对象的结构)
    • 当您想要将算法与其使用的对象分离时,您将使用visitor。你要做的是,这个访问者被传递给许多不同的对象,通常是一个层次结构(据说它们接受访问者),这个访问者根据它在特定时刻访问的对象类型执行特定操作。通过这种方式,您可以让访问者对特定对象执行任何操作,而无需在对象本身中指定这些操作(这就是为什么它是行为的)。这是一种抽象方法,它没有在对象本身中定义

    我喜欢认为decorator允许避免继承然后扩展类,这是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总是添加巧克力配料。因此,现在你可以通过将相关厨师传递给其构造器来吃巧克力饼干或巧克力蛋糕。另一方面,访问者对对象进行操作,并根据其正在访问的对象决定执行某些操作

    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
         }
    }
    

    按照我的理解,访客代表了我们可能想要对某个对象或与之相关的行为,但这些行为不一定是某个对象固有的,并且在关系上是水平的。例如,我可以为一辆汽车“做一个营销宣传”,但我不会将汽车对象编程为具有“CreateMarkingPitch”功能,因为这将是在我的汽车对象上创建许多功能的一个滑坡

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

    它们都向现有对象“添加功能”,而不修改原始类。区别在于:

    使用decorator可以添加包装此对象的基本功能的功能(例如,除了执行一些基本操作之外,还可以将其写入日志,除了将文件写入磁盘之外,还可以对其进行加密)。这还允许我们创建不同的装饰器组合,而无需对每个可能的场景进行子类化

    对于访问者您添加了一个全新的行为,您不想将其定义为基本组件类本身的一部分(甚至不想将其定义为基本功能的包装器),例如,因为单一责任原则、打开-关闭原则等。 当同一类型的不同子类之间的行为不同时(如果没有任何复杂的子类结构,只有一个类,那么您可以创建一个新类并通过组合包含原始类,并且仍然实现不影响或修改原始类的目标),这一点尤其有用。这样,您就可以避免类似
    if(a是具体类1){…}或者if(a是具体类2){…}
    这样的代码,而无需编写虚拟方法


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

    我认为装饰器模式的方式是在运行时向对象添加功能。我可以在程序运行时,通过将对象包装在一个装饰器类中(装饰器类可以扩展其方法),向对象添加行为

    对于访问者模式,我喜欢在“一组”相同类型的对象上执行操作并收集信息。假设我有10个具体的ve类