策略模式和访客模式有什么区别?

发布于 2024-12-23 10:02:13 字数 217 浏览 1 评论 0原文

我很难理解这两种设计模式。

您能否给我上下文信息或示例,以便我可以得到清晰的想法并能够映射两者之间的差异。

谢谢。

在此处输入图像描述

在此输入图像描述

I have trouble understanding these two design patterns.

Can you please give me contextual information or an example so I can get a clear idea and be able to map the difference between the two of them.

Thanks.

enter image description here

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

×纯※雪 2024-12-30 10:02:13

策略模式类似于1:多关系。当存在一种类型的对象并且我想对其应用多个操作时,我使用策略模式。例如,如果我有一个封装视频剪辑的 Video 类,我可能想以不同的方式压缩它。所以我创建了一堆策略类:

MpegCompression
AviCompression
QuickTimeCompression

等等。

我认为访问者模式是一种多:多关系。假设我的应用程序不仅包含视频,还包含音频剪辑。如果我坚持使用策略模式,我必须复制我的压缩类 - 一个用于视频,一个用于音频:

MpegVideoCompression
MpegAudioCompression

依此类推...

如果我切换到访问者模式,我就没有复制策略类。我通过添加方法来实现我的目标:

MpegCompressionVisitor::compressVideo(Video object)    
MpegCompressionVisitor::compressAudio(Audio object)

[更新:使用Java]
我在 Java 应用程序中使用了访问者模式。结果与上面描述的有点不同。这是此示例的 Java 版本。

// Visitor interface
interface Compressor {

  // Visitor methods
  void compress(Video object);
  void compress(Audio object);
}

// Visitor implementation
class MpegCompressor implements Compressor {
  
  public void compress(Video object) {
    // ...
  }

  public void compress(Audio object) {
    // ...
  }
}

现在要访问的接口和类:

interface Compressible {

  void accept(Compressor compressor);
}

class Video implements Compressible {

  // If the Compressor is an instance of MpegCompressionVisitor,
  // the system prints "Mpeg video compression"
  void accept(Compressor compressor) {
    compressor.compress(this);
}

The strategy pattern is like a 1:many relationship. When there is one type of object and I want to apply multiple operations to it, I use the strategy pattern. For example, if I have a Video class that encapsulates a video clip, I might want to compress it in different ways. So I create a bunch of strategy classes:

MpegCompression
AviCompression
QuickTimeCompression

and so on.

I think of the visitor pattern as a many:many relationship. Let's say my application grows to to include not just video, but audio clips as well. If I stick with the strategy pattern, I have to duplicate my compression classes-- one for video and one for audio:

MpegVideoCompression
MpegAudioCompression

and so on...

If I switch to the visitor pattern, I do not have to duplicate the strategy classes. I achieve my goal by adding methods:

MpegCompressionVisitor::compressVideo(Video object)    
MpegCompressionVisitor::compressAudio(Audio object)

[UPDATE: with Java]
I used the visitor pattern in a Java app. It came out a little different than described above. Here is a Java version for this example.

// Visitor interface
interface Compressor {

  // Visitor methods
  void compress(Video object);
  void compress(Audio object);
}

// Visitor implementation
class MpegCompressor implements Compressor {
  
  public void compress(Video object) {
    // ...
  }

  public void compress(Audio object) {
    // ...
  }
}

And now the interface and class to be visited:

interface Compressible {

  void accept(Compressor compressor);
}

class Video implements Compressible {

  // If the Compressor is an instance of MpegCompressionVisitor,
  // the system prints "Mpeg video compression"
  void accept(Compressor compressor) {
    compressor.compress(this);
}
眼中杀气 2024-12-30 10:02:13

策略模式用于将各种算法公开给标准化接口。一个典型的例子是排序实用程序,它允许用户(程序员)在通过相同接口调用的各种排序算法之间进行选择。

访问者模式存在于不同的层面。它详细介绍了一种机制,通过该机制,对象可以接受对另一个对象(访问者)的引用,该对象公开目标对象可以调用其自身的预定接口。当然,不同的访问者会呈现相同的界面,但有不同的实现。

回到我们的示例,排序算法的集合可以通过策略模式或访问者模式来实现。

使用策略方法,每个算法都呈现相同的接口,并以目标对象数组作为参数。对于访问者模式,目标数组将采用“访问”算法作为参数。在这种情况下,在我们的示例中,目标将“accept()”选定的访问者,并在调用目标的排序方法时调用其“visit()”方法。

同一枚硬币的两面……

这有道理吗?

A Strategy pattern is used to expose various algorithms to a standardized interface. A typical example could be a sort utility that would let the user (programmer) choose between various sort algorithms each called via the same interface.

A Visitor pattern lives at a different level. It details a mechanism with which objects can accept a reference to another object (the visitor) which exposes a predetermined interface that the target object can call upon itself. Of course, different visitors would present the same interface but have different implementations.

Coming back to our example, a collection of sort algorithms could be implemented either via the Strategy pattern or via the Visitor pattern.

With the Strategy method, each algorithm presents the same interface and takes arrays of target objects as parameters for example. With the Visitor pattern, it would be the target array that takes the "visiting" algorithm as a parameter. In this case, the target would "accept()" the selected visitor and call its "visit()" method upon invocation of the target's sort method in our example.

Two sides of the same coin...

Does this make sense?

痴梦一场 2024-12-30 10:02:13

访问者是一种策略,但具有多种方法,并且允许双重调度。访问者还允许在运行时在两个具体对象之间进行安全绑定。

注意:这是用 Java 编写的示例。例如,C# 引入了 dynamic 关键字,因此双重调度的示例在 C# 中没有用处。

策略模式

考虑以下示例和输出:

package DesignPatterns;

public class CarGarageStrategyDemo 
{
    public static interface RepairStrategy
    {
        public void repair(Car car);
    }

    public static interface Car
    {
        public String getName();
        public void repair(RepairStrategy repairStrategy);
    }

    public static class PorscheRepairStrategy implements RepairStrategy
    {
        @Override
        public void repair(Car car) {
            System.out.println("Repairing " + car.getName() + " with the Porsche repair strategy");
        }
    }
    
    public static class FerrariRepairStrategy implements RepairStrategy
    {
        @Override
        public void repair(Car car) {
            System.out.println("Repairing " + car.getName() + " with the Ferrari repair strategy");
        }
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }

        @Override
        public void repair(RepairStrategy repairStrategy) {
            repairStrategy.repair(this);
        }
    }

    public static void main(String[] args)
    {
        Car porsche = new Porsche();
        porsche.repair(new PorscheRepairStrategy()); //Repairing Porsche with the porsche repair strategy
    }
}

如果策略和主题之间没有直接关系,则Strategy 模式可以正常工作。例如,我们不希望发生以下情况:

...
    public static void main(String[] args)
    {
        Car porsche = new Porsche();
        porsche.repair(new FerrariRepairStrategy()); //We cannot repair a Porsche as a Ferrari!
    }
...

因此在这种情况下我们可以使用访问者模式。

访问者

问题

考虑下面的代码:

public class CarGarageVisitorProblem
{
    public static interface Car
    {
        public String getName();
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }
    }

    public static class Ferrari implements Car
    {
        public String getName()
        {
            return "Ferrari";
        }
    }

    public void repair(Car car)
    {
        System.out.println("Applying a very generic and abstract repair");
    }

    public void repair(Porsche car)
    {
        System.out.println("Applying a very specific Porsche repair");
    }

    public void repair(Ferrari car)
    {
        System.out.println("Applying a very specific Ferrari repair");
    }

    public static void main(String[] args)
    {
        CarGarageVisitorProblem garage = new CarGarageVisitorProblem();
        Porsche porsche = new Porsche();
        garage.repair(porsche); //Applying a very specific Porsche repair
    }
}

输出为 Applying a very Specific Porsche Repair
问题是这一行不是抽象的,而是具体的:

Porsche porsche = new Porsche();

我们想把它写成(或者在构造函数中注入 Car 的实例,我们想应用依赖倒置原则):

Car porsche = new Porsche();

但是当我们更改此行,输出将是:

Applying a very generic and abstract repair

不是我们想要的!

解决方案;使用双重调度(和访问者模式)

package DesignPatterns;

public class CarGarageVisitorExample 
{
    public static interface Car
    {
        public String getName();
        public void repair(RepairVisitorInterface repairVisitor);
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }

        public void repair(RepairVisitorInterface repairVisitor)
        {
            repairVisitor.repair(this);
        }
    }

    public static class Ferrari implements Car
    {
        public String getName()
        {
            return "Ferrari";
        }

        public void repair(RepairVisitorInterface repairVisitor)
        {
            repairVisitor.repair(this);
        }
    }

    public static interface RepairVisitorInterface
    {
        public void repair(Car car);
        public void repair(Porsche car);
        public void repair(Ferrari car);
    }

    public static class RepairVisitor implements RepairVisitorInterface
    {
        public void repair(Car car)
        {
            System.out.println("Applying a very generic and abstract repair");
        }

        public void repair(Porsche car)
        {
            System.out.println("Applying a very specific Porsche repair");
        }

        public void repair(Ferrari car)
        {
            System.out.println("Applying a very specific Ferrari repair");
        }
    }

    public static void main(String[] args)
    {
        CarGarageVisitor garage = new CarGarageVisitor();
        Car porsche = new Porsche();
        porsche.repair(new RepairVisitor()); //Applying a very specific Porsche repair
    }
}

由于方法重载,访问者和主题(汽车)之间存在具体的绑定。保时捷不可能像法拉利一样被修理,因为它使用方法重载。我们还通过实现此方法解决了前面解释的问题(我们不能使用Dependency Inversion):

public void repair(RepairVisitorInterface repairVisitor)
{
    repairVisitor.repair(this);
}

this 引用将返回对象的具体类型,而不是抽象类型(汽车)类型。

A Visitor is a strategy but with multiple methods and it allows Double dispatch. The Visitor also allows for safe binding between two concrete objects at runtime.

Note: This is an example written in Java. For example C# introduced the dynamic keyword, therefor the example of double dispatch is not useful in C#.

Strategy pattern

Consider the following example and the output:

package DesignPatterns;

public class CarGarageStrategyDemo 
{
    public static interface RepairStrategy
    {
        public void repair(Car car);
    }

    public static interface Car
    {
        public String getName();
        public void repair(RepairStrategy repairStrategy);
    }

    public static class PorscheRepairStrategy implements RepairStrategy
    {
        @Override
        public void repair(Car car) {
            System.out.println("Repairing " + car.getName() + " with the Porsche repair strategy");
        }
    }
    
    public static class FerrariRepairStrategy implements RepairStrategy
    {
        @Override
        public void repair(Car car) {
            System.out.println("Repairing " + car.getName() + " with the Ferrari repair strategy");
        }
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }

        @Override
        public void repair(RepairStrategy repairStrategy) {
            repairStrategy.repair(this);
        }
    }

    public static void main(String[] args)
    {
        Car porsche = new Porsche();
        porsche.repair(new PorscheRepairStrategy()); //Repairing Porsche with the porsche repair strategy
    }
}

The Strategy pattern is working fine if there is no direct relationship between the strategy and the subject. For example, we don't want the following to happen:

...
    public static void main(String[] args)
    {
        Car porsche = new Porsche();
        porsche.repair(new FerrariRepairStrategy()); //We cannot repair a Porsche as a Ferrari!
    }
...

So in this case we can use the visitor pattern.

Visitor

The problem

Consider the code below:

public class CarGarageVisitorProblem
{
    public static interface Car
    {
        public String getName();
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }
    }

    public static class Ferrari implements Car
    {
        public String getName()
        {
            return "Ferrari";
        }
    }

    public void repair(Car car)
    {
        System.out.println("Applying a very generic and abstract repair");
    }

    public void repair(Porsche car)
    {
        System.out.println("Applying a very specific Porsche repair");
    }

    public void repair(Ferrari car)
    {
        System.out.println("Applying a very specific Ferrari repair");
    }

    public static void main(String[] args)
    {
        CarGarageVisitorProblem garage = new CarGarageVisitorProblem();
        Porsche porsche = new Porsche();
        garage.repair(porsche); //Applying a very specific Porsche repair
    }
}

The output is Applying a very specific Porsche repair.
The problem is that this line is not abstract, but concrete:

Porsche porsche = new Porsche();

We want to write it as (or inject an instance of Car in the constructor, we want to apply the Dependency Inversion Principle):

Car porsche = new Porsche();

But when we change this line, the output will be:

Applying a very generic and abstract repair

Not what we want!

The solution; using double dispatch (and the Visitor pattern)

package DesignPatterns;

public class CarGarageVisitorExample 
{
    public static interface Car
    {
        public String getName();
        public void repair(RepairVisitorInterface repairVisitor);
    }

    public static class Porsche implements Car
    {
        public String getName()
        {
            return "Porsche";
        }

        public void repair(RepairVisitorInterface repairVisitor)
        {
            repairVisitor.repair(this);
        }
    }

    public static class Ferrari implements Car
    {
        public String getName()
        {
            return "Ferrari";
        }

        public void repair(RepairVisitorInterface repairVisitor)
        {
            repairVisitor.repair(this);
        }
    }

    public static interface RepairVisitorInterface
    {
        public void repair(Car car);
        public void repair(Porsche car);
        public void repair(Ferrari car);
    }

    public static class RepairVisitor implements RepairVisitorInterface
    {
        public void repair(Car car)
        {
            System.out.println("Applying a very generic and abstract repair");
        }

        public void repair(Porsche car)
        {
            System.out.println("Applying a very specific Porsche repair");
        }

        public void repair(Ferrari car)
        {
            System.out.println("Applying a very specific Ferrari repair");
        }
    }

    public static void main(String[] args)
    {
        CarGarageVisitor garage = new CarGarageVisitor();
        Car porsche = new Porsche();
        porsche.repair(new RepairVisitor()); //Applying a very specific Porsche repair
    }
}

Because of method overloading, there is a concrete binding between the visitor and the subject (Car). There is no way a Porsche can be repaired as a Ferrari, since it uses method overloading. Also we solved the previously explained problem (that we cannot use Dependency Inversion), by implementing this method:

public void repair(RepairVisitorInterface repairVisitor)
{
    repairVisitor.repair(this);
}

The this reference will return the concrete type of the object, not the abstract (Car) type.

橘虞初梦 2024-12-30 10:02:13

访问者就像一夜情——你在调用接受函数时创建它,然后它们分开,访问者可以从内存中清除,它不会为使用它的类占用任何空间。

该策略就像婚姻 - 您创建了对象,它存在于使用它的类中,占用内存,有一个房间并在早上给自己煮咖啡:)。
当然,他们可以离婚并转入另一个阶层,但该阶层也将生活在其所有者的环境中。

希望它能帮助你记住:)

The visitor is like a one-night stand - you create it when you call the accept function and then they get separated and the visitor can be cleaned from the memory, it doesn't take any room for the class that use it.

The strategy is like a marriage - you create the object, it lives in the class that uses it, takes memory, has a room and makes itself a coffee in the morning :) .
Of course they can get a divorce and switch to another class but that class would also live in its owner's context.

Hope it helps you remember :)

记忆之渊 2024-12-30 10:02:13

决定性的区别在于,Visitor 使用运算符重载为元素的子类提供不同的行为。它知道它正在处理或访问的事物类型。

与此同时,策略将在其所有实现中保持一致的接口。

访问者用于允许对象的子部分使用一致的方法来做某事。策略用于允许依赖注入如何做某事。

所以这将是一个访问者:

class LightToucher : IToucher{
    string Touch(Head head){return "touched my head";}
    string Touch(Stomach stomach){return "hehehe!";}
}

与另一个这种类型的

class HeavyToucher : IToucher{
   string Touch(Head head){return "I'm knocked out!";}
   string Touch(Stomach stomach){return "oooof you bastard!";}
}

访问者我们有一个类,然后可以使用这个访问者来完成其工作,并根据它进行更改:

class Person{
    IToucher visitor;
    Head head;
    Stomach stomach;
    public Person(IToucher toucher)
    {
          visitor = toucher;

          //assume we have head and stomach
    }

    public string Touch(bool aboveWaist)
    {
         if(aboveWaist)
         {
             visitor.Touch(head);
         }
         else
         {
             visitor.Touch(stomach);
         }
    }
}

所以如果我们这样做
var person1 = new Person(new LightToucher());
var person2 = new Person(new HeavyToucher());

        person1.Touch(true); //touched my head
        person2.Touch(true);  //knocked me out!

The defining difference is that the Visitor offers a different behavior for subclasses of the element, using operator overloading. It knows the sort of thing it is working upon, or visiting.

A Strategy, meanwhile, will hold a consistent interface across all its implementations.

A visitor is used to allow subparts of an object to use a consistent means of doing something. A strategy is used to allow dependency injection of how to do something.

So this would be a visitor:

class LightToucher : IToucher{
    string Touch(Head head){return "touched my head";}
    string Touch(Stomach stomach){return "hehehe!";}
}

with another one of this type

class HeavyToucher : IToucher{
   string Touch(Head head){return "I'm knocked out!";}
   string Touch(Stomach stomach){return "oooof you bastard!";}
}

We have a class that can then use this visitor to do its work, and change based upon it:

class Person{
    IToucher visitor;
    Head head;
    Stomach stomach;
    public Person(IToucher toucher)
    {
          visitor = toucher;

          //assume we have head and stomach
    }

    public string Touch(bool aboveWaist)
    {
         if(aboveWaist)
         {
             visitor.Touch(head);
         }
         else
         {
             visitor.Touch(stomach);
         }
    }
}

So if we do this
var person1 = new Person(new LightToucher());
var person2 = new Person(new HeavyToucher());

        person1.Touch(true); //touched my head
        person2.Touch(true);  //knocked me out!
胡大本事 2024-12-30 10:02:13

我将策略模式视为将方法/策略注入对象的一种方式,但通常该方法的签名采用一些值参数并返回结果,因此它不与策略的用户耦合:
来自 Wikipedia

class Minus : ICalculateStrategy {
    public int Calculate(int value1, int value2) {
        return value1 - value2;
    }
}

访问者通过双重调度与用户耦合,并且通常保持状态。
很好的例子这里,我将从那里复制:

public class BlisterPack
{
    // Pairs so x2
    public int TabletPairs { get; set; }
}

public class Bottle
{
    // Unsigned
    public uint Items { get; set; }
}

public class Jar
{
    // Signed
    public int Pieces { get; set; }
}

public class PillCountVisitor : IVisitor
{
    public int Count { get; private set; }

    #region IVisitor Members

    public void Visit(BlisterPack blisterPack)
    {
        Count += blisterPack.TabletPairs * 2;
    }

    public void Visit(Bottle bottle)
    {
        Count += (int) bottle.Items;
    }

    public void Visit(Jar jar)
    {
        Count += jar.Pieces;
    }

    #endregion
}

public class BlisterPack : IAcceptor
{
    public int TabletPairs { get; set; }

    #region IAcceptor Members

    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }

    #endregion
}

如您所见,访问者有状态(public int Count),并且它在已知类型 BlisterPack、Bottle、Jar 的列表上进行操作。因此,如果您想支持新类型,您需要通过添加该类型来更改所有访问者。

此外,由于“visitor.Visit(this);”,它与它所操作的类型耦合在一起。如果我删除或更改瓶子中的“物品”属性,会发生什么情况? ...所有访客都会失败。

I see strategy pattern as a way to inject a method/strategy into an object, but typically the signature of that method takes some value params and returns a result so it's not coupled with the user of the strategy:
From Wikipedia :

class Minus : ICalculateStrategy {
    public int Calculate(int value1, int value2) {
        return value1 - value2;
    }
}

Visitor instead is coupled with the user through double dispatch and typically keeps state.
Good example here, I'll just copy from there:

public class BlisterPack
{
    // Pairs so x2
    public int TabletPairs { get; set; }
}

public class Bottle
{
    // Unsigned
    public uint Items { get; set; }
}

public class Jar
{
    // Signed
    public int Pieces { get; set; }
}

public class PillCountVisitor : IVisitor
{
    public int Count { get; private set; }

    #region IVisitor Members

    public void Visit(BlisterPack blisterPack)
    {
        Count += blisterPack.TabletPairs * 2;
    }

    public void Visit(Bottle bottle)
    {
        Count += (int) bottle.Items;
    }

    public void Visit(Jar jar)
    {
        Count += jar.Pieces;
    }

    #endregion
}

public class BlisterPack : IAcceptor
{
    public int TabletPairs { get; set; }

    #region IAcceptor Members

    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }

    #endregion
}

As you can see the visitor has state(public int Count) and it operates on a list of know types BlisterPack, Bottle, Jar. So if you want to support a new type you need to change all visitors by adding that type.

Also it's coupled with the types it operates on because of "visitor.Visit(this);". What would happen if I remove or change the "Items" property form bottle? ... all visitors would fail.

梦一生花开无言 2024-12-30 10:02:13

如果我们查看 GoF 书中这两种模式的 UML,我们会发现它们毫无相似之处。

访客

访客 UML


策略

Strategy UML


从图中可以看出一些重要的差异。

  • 策略是基于组合的。访客没有组合关系。
  • 策略基于接口编码。访问者基于编码实现。
  • 策略以多种方式实现一项操作。访问者执行多种操作。

仅 UML 并不能捕获驱动这些模式的不同动机。

  • 策略是针对没有一流函数的语言的面向对象解决方案。由于现代语言采用了闭包或 lambda,因此对策略模式的需求减少了。
  • Visitor 是一种面向对象的解决方案,适用于没有模式匹配或多重分派的语言。随着现代语言采用这些功能,Visitor 也变得过时了。

If we look at the UML for these two patterns from the GoF book, we see they are nothing alike.

Visitor:

Visitor UML


Strategy:

Strategy UML


Some important differences stand out from the diagrams.

  • Strategy is based on composition. Visitor has no composition relationship.
  • Strategy is based on coding to an interface. Visitor is based on coding to an implementation.
  • Strategy implements one operation in multiple ways. Visitor implements multiple operations.

UML alone does not capture the different motivations driving these patterns.

  • Strategy is an object-oriented solution for languages without first-class functions. As modern languages adopt closures or lambdas, there is less need for the Strategy Pattern.
  • Visitor is an object-oriented solution for languages without pattern matching or multiple dispatch. As modern languages adopt these features, Visitor too becomes obsolete.
染柒℉ 2024-12-30 10:02:13

两者都是调度的方法(在运行时决定调用哪个函数)。区别在于你是支持算法(访问者)还是对象(策略):

  • 使用策略模式,我们在主对象中注入一个策略(对象/函子/lambda),每次调用特定方法时,我们都会注入一个策略(对象/函子/lambda)。 委托调用当前活动的策略来执行。
  • 使用访问者模式,我们不会从对象委托,而是将对象扔给所谓的访问者对象/函数,该对象/函数基于此参数选择(通常通过重载解析)它想要应用的算法

因此,如果您有一个对象和多种算法 (1:n),那么策略就有意义,反之亦然,如果您有多个对象和只有一种算法,则最好使用访问者模式 (n:1)。

但是如果您有多个对象和多种算法怎么办?

在这种情况下,选择的算法将取决于另一个参数,对吧?因此,我们使用双重调度方法,该方法基于我们的对象和附加参数来选择算法。这通常也是通过重载解析来完成的,因此该模式将大部分类似于访问者模式 (n:n)。

过度简化*:

begin(obj); // <-- visitor
obj.begin(); // <-- strategy

(*) 这种比较是在以下假设下进行的:begin() 方法根据 obj 中设置的当前策略改变其行为,而对于访问者,我们必须假设有不同的 begin () 重载浮动(但通常捆绑在一起在访问者对象中),并且根据我们放入其中的对象选择正确的重载。

Both are methods of dispatching (deciding at runtime which function to call). The difference lies in whether you side with the algorithm (visitor) or with the object (strategy):

  • With the strategy pattern we inject a strategy (object / functor / lambda) in our main object, and every time a specific method is called we delegate that call to the currently active strategy to execute.
  • With a visitor pattern we don't delegate from the object but instead we throw our object at a so called Visitor object/function, which based on this parameter chooses (usually through overload resolution) the algorithm it wants to apply to our passed object.

Consequently, strategy makes sense if you have one object and multiple algorithms (1:n), vice versa if you have multiple objects and just one algorithm you're better off using the visitor patter (n:1).

But what if you have multiple objects and multiple algorithms?

In this case, the algorithm chosen would depend on another parameter, right? So we use a double dispatching method which bases the selection of the algorithm on our object and the additional parameter. This is also often done through overload resolution, so that pattern will resemble the visitor pattern mostly (n:n).

Oversimplified*:

begin(obj); // <-- visitor
obj.begin(); // <-- strategy

(*) This comparison works under the assumption that the begin() method alters its behaviour based on the current strategy set in obj, whereas for the visitor we have to assume that there are different begin() overloads floating around (but usually bundled together in a visitor object) and the right one is picked based on the object we put into it.

请帮我爱他 2024-12-30 10:02:13

对我来说,第二张图似乎是访问者模式...因为对于策略模式,包含数据结构的类往往只有一个,没有子类(或者子类保持这部分的相同行为)。该策略适用于同一结构上的不同操作。

Seems like the second graph is Visitor Pattern to me...Since for strategy pattern, the class contains data structure tends to be only one, no subclass(Or the subclass stays same behavior of this part). The strategy is for different operations on the same structure.

冬天旳寂寞 2024-12-30 10:02:13

我会尝试做出最简短的答案。

这两种模式相互补充:例如,您可以使用访问者来更改图的所有节点上的策略。

I'll try to make the shortest answer.

The two patterns complement one another: for instance, you could use a visitor to change the strategies on all the nodes of a graph.

瞄了个咪的 2024-12-30 10:02:13

关键的不同之处之一是访问者模式允许您将不同的逻辑(访问者)插入现有的类(元素)中,只需对其进行最小的更改。它喜欢您公开一种机制,让其他人在您的类上运行逻辑,而无需更改实现你们班的。

One of the key different is the Visitor pattern allows you to plug in different logic (visitors) into an existing class (element) with minimal change to it.It likes you expose a mechanism other people to run logic on your class without changing the implementation of your class.

哑剧 2024-12-30 10:02:13

它们的区别是:

  1. 动机
  2. 意图
  3. 实施

不确定比较两个不同的事物会得到什么,但比较策略访客

两者有什么相同之处,让人去寻找他们的不同之处呢?

Their differences are :

  1. Motivation
  2. Intent
  3. Implementation

Not sure what is gained from comparing two different things but compare Strategy to Visitor.

What is same about the two to make one look for their differences?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文