Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 战略模式和访客模式有什么区别?_Oop_Design Patterns_Strategy Pattern_Visitor Pattern - Fatal编程技术网

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

Oop 战略模式和访客模式有什么区别?,oop,design-patterns,strategy-pattern,visitor-pattern,Oop,Design Patterns,Strategy Pattern,Visitor Pattern,我很难理解这两种设计模式 你能给我一个上下文信息或者一个例子,这样我就可以得到一个清晰的想法,并且能够映射出两者之间的差异 谢谢 它们的区别是: 动机 意图 实施 不知道比较两种不同的东西能得到什么,但要比较一下 这两种方法有什么相同之处,可以让一个人看到它们的不同之处?一种策略模式用于将各种算法公开到一个标准化的界面。一个典型的例子是排序实用程序,它允许用户(程序员)在通过同一接口调用的各种排序算法之间进行选择 访问者模式处于不同的级别。它详细介绍了一种机制,通过该机制,对象可以接受对另一个

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

你能给我一个上下文信息或者一个例子,这样我就可以得到一个清晰的想法,并且能够映射出两者之间的差异

谢谢


它们的区别是:

  • 动机
  • 意图
  • 实施
  • 不知道比较两种不同的东西能得到什么,但要比较一下


    这两种方法有什么相同之处,可以让一个人看到它们的不同之处?

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

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

    回到我们的示例,可以通过Strategy模式或Visitor模式实现一组排序算法

    在策略方法中,每种算法都提供相同的接口,并以目标对象数组为参数。对于访问者模式,目标数组将使用“访问者”算法作为参数。在本例中,目标将“接受()”所选访问者,并在我们的示例中调用目标的sort方法时调用其“visit()”方法

    同一枚硬币的两面


    这有意义吗?

    战略模式就像一种1:many关系。当存在一种类型的对象并且我想对其应用多个操作时,我使用策略模式。例如,如果我有一个封装视频剪辑的视频类,我可能希望以不同的方式压缩它。因此,我创建了一系列策略类:

    MpegCompression
    AviCompression
    QuickTimeCompression
    
    等等

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

    MpegVideoCompression
    MpegAudioCompression
    
    等等

    如果切换到访问者模式,则不必复制策略类。我通过添加以下方法来实现我的目标:

    MpegCompressionVisitor::compressVideo(Video object)    
    MpegCompressionVisitor::compressAudio(Audio object)
    
    [更新:使用Java] 我在Java应用程序中使用了访问者模式。结果与上面描述的略有不同。下面是这个示例的Java版本

    //访问者界面
    接口压缩器{
    //访客方法
    void压缩(视频对象);
    无效压缩(音频对象)
    }
    //访问者实现
    类MpegCompressor执行压缩机{
    公共空压缩(视频对象){
    System.out.println(“Mpeg视频压缩”);
    }
    公共空压缩(音频对象){
    ...
    }
    }
    
    现在是要访问的接口和类:

    界面可压缩{
    无效接受(压缩机);
    }
    类视频实现可压缩{
    //如果压缩机是MpegCompressionVisitor的实例,
    //系统打印“Mpeg视频压缩”
    无效接受(压缩机){
    压缩(这个);
    }
    
    定义上的区别在于,访问者使用运算符重载为元素的子类提供了不同的行为。它知道自己正在处理或访问的内容

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

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

    因此,这将是一位访客:

    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 LightToucher()); var person2=新人(new HeavyToucher())


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

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

    取而代之的是,访问者通过双重分派和用户耦合,并且通常保持状态。 很好的例子,我将从那里复制:

    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
    }
    
    正如您所看到的,访问者具有state(public int Count),并且它在已知类型的列表上运行。因此,如果您想要支持一个新类型,您需要通过添加该类型来更改所有访问者


    此外,由于“visitor.Visit(this);”的原因,它还与它所操作的类型相结合。如果我删除或更改“Items”,会发生什么情况属性表单瓶子?…所有访问者都会失败。

    访问者就像一夜情一样-当您调用accept函数时创建它,然后它们会分离,访问者可以从内存中清除,使用它的类不会占用任何空间

    这个策略就像一场婚姻——你创建了一个对象,它生活在使用它的班级里,占用了记忆,有一个房间,早上自己煮咖啡:)。 当然,他们可以离婚,换到另一个阶级,但这个阶级也会生活在它主人的环境中


    希望它能帮助您记住:)

    如果您只有一个上下文或元素,并且需要在该上下文上执行不同的操作,那么您可以
    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
    }
    
    Applying a very generic and abstract repair