代码之家  ›  专栏  ›  技术社区  ›  TryinHard JohanShogun

多态性与策略模式

  •  59
  • TryinHard JohanShogun  · 技术社区  · 9 年前

    两者之间的区别是什么 Strategy 模式和 Polymorphism 在Java中?

    我感到困惑的是,通过Strategy Pattern实现的一切基本上都可以通过多态性实现。如果我在这方面有错,请纠正我。

    请给我举个例子,消除我的困惑。

    10 回复  |  直到 9 年前
        1
  •  52
  •   Community c0D3l0g1c    7 年前

    对我来说 CKing 这篇文章和维基百科中的例子已经很清楚了,但我会尝试给你一个新的例子。正如他们所说,战略模式主要是 一种在运行时改变算法行为的方法 当然,您可以通过许多不同的方式实现这一点(例如保持值和使用switch case,但这不会像Strategy Pattern那样好)。

    假设你正在开发一个基于回合的策略游戏 单位 : 步兵 坦克 (单位的子类)。你的地形可能是 平原 , 铁路 森林 .

    class Unit{
        MovementStrategy ms;      
        final int baseMovement;
        int x,y;
    
        public Unit(int baseMovement){
            this.baseMovement = baseMovement;
        }
    
        abstract void fire();
    
        void moveForward(){
            x = x + ms.getHexagonsToMove(baseMovement);
        }
    
        void setMovementStrategy(MovementStrategy ms){
            this.ms = ms;
        }
    }
    

    任何Unit子类都必须实现 火() 方法,因为 对他们来说会完全不同 (坦克发射重距离子弹,步兵发射数发短距离轻子弹)。在本例中,我们使用普通多态性/继承,因为 火() 对于任何单元,方法都会非常不同,并且 在比赛中它不会改变 .

    class Infantry extends Unit{
        public Infantry(){
            super(2);
        }
    
        void fire(){
            //whatever
        }
    }
    
    class Tank extends Unit{
        public Tank(){
            super(5);
        }
    
        void fire(){
            //whatever
        }
    }
    

    单位也可以移动,并有一个字段 基本移动 它可以行走的六边形的数量。我们开发的是一个战略游戏,而不是真实世界的模拟,所以我们不关心它们如何移动,我们只想在它们的坐标上添加一个值(在我的示例中,我只使用X坐标,以便获得更简单的代码)。如果所有地形都一样,我们就不需要任何战略目标……但是 我们需要在运行时更改move()方法的行为!

    因此,我们实现了不同的 移动策略 类,我们编程游戏以触发 设置移动策略() 在每个六边形上移动的任何单位。我们甚至不需要在Unit子类中编写任何其他内容。

    interface MovementStrategy{
        public int getHexagonsToMove(int base);
    }
    
    class PlainMovementStrategy implements MovementStrategy{
        public int getHexagonsToMove(int base){
            return base;
        }
    }
    
    class RailroadMovementStrategy implements MovementStrategy{
        public int getHexagonsToMove(int base){
            return base*3;
        }
    }
    
    class ForestMovementStrategy implements MovementStrategy{
        public int getHexagonsToMove(int base){
            return (int)(base/2);
        }
    }   
    

    现在,如果有的话 单元 在内部移动 森林 ,我们打电话

    unit.setMovementStrategy(new ForestMovementStrategy());
    

    一旦它进入 平原 ,我们做到了:

    unit.setMovementStrategy(new PlainMovementStrategy());
    

    现在我们可以根据地形改变单位移动的距离,而不需要在任何子类中重写。

    我希望这有助于您更好地理解差异。

        2
  •  32
  •   Community c0D3l0g1c    7 年前

    我感到困惑的是,通过Strategy Pattern实现的一切基本上都可以通过多态性实现。

    没有方向盘你不能开车。这并不意味着方向盘就是汽车。同样,Strategy模式依赖于多态性,但这并不意味着它们是相同的。

    Strategy模式的目的是促进使用组合(has-a)而不是继承(is-a)。您的类不是从超级类继承行为,而是在单独的类中定义行为,并且您的类具有对它的引用。

    举个例子,看看 this 答案很好。

        3
  •  14
  •   Premraj    3 年前
    • 基本区别: 多态性 是编程语言概念,以及 战略模式 是其中之一 behavioral design pattern of GoF .

    • 多态性 是为几种不同的底层数据类型提供一个接口。

      • 例子: 无论使用哪种类型的实际转向机构,方向盘(即接口)都是相同的。也就是说,无论您的汽车是手动转向、动力转向还是齿轮齿条转向,方向盘的工作原理都是一样的。因此,一旦你知道如何操作方向盘,你就可以驾驶任何类型的汽车。

      • 在编程中, 多态性 以两种方式实现:

        • 早期绑定/静态/编译时多态性(例如:函数重载)
        • 后期绑定/动态/运行时多态性(例如:函数重写)
    • A. Strategy pattern 定义了一组可以互换使用的算法。

      • 策略模式是一种动态模式(您希望如何在软件中运行行为?)。

      • 核心java示例: java.util.Comparator#compare() ,由其他人执行 Collections#sort() .

      • 运输方式 类似于 战略设计模式 我们每天使用汽车、自行车、公共汽车、当地火车等不同的方式去上班。

        4
  •  10
  •   Marko Topolnik    9 年前

    如果您正在建立一个类比,其中:

    • 在一种情况下,您有几个可重写的方法;
    • 在另一种情况下,您有一个具有多个实现的Strategy接口,

    那么不同的是耦合程度,在第一种情况下耦合程度非常强,而在第二种情况下,任何外来代码都可以通过贡献其Strategy实现来参与类的逻辑。

        5
  •  8
  •   Edwin Dalorzo    6 年前

    问: 策略模式和多态性之间的区别是什么 在Java中?

    这些问题无疑令人困惑,因为最初这两种想法之间似乎没有任何联系。

    多态性在编程中是一个更广泛的概念,是的,Java中的策略模式使用了一种形式的多态性 inclusion polymorphism 实现其目的,但这绝不是唯一存在的多态性类型,也不是实现策略模式的唯一方法,正如我将很快演示的那样。

    多态性也不仅仅存在于Java或面向对象编程语言中。不同形式的多态性存在于所有编程范式中,而不是所有语言中,您必须使用多态性来实现策略模式(例如函数语言)。

    有关此主题的进一步讨论,请阅读 this other answer 在那里,我们讨论了多态性是否可能没有继承,我为其他类型的多态性提供了有趣的参考和示例,如参数多态性和ad-hoc多态性。

    理想情况下,这将向您揭示多态性是一个更大的概念,它超越了面向对象编程的界限,甚至超越了继承和子类型化。

    问: 我很困惑,无论通过战略模式实现什么 基本上通过多态性是可能的。如果我错了,请纠正我 看待

    从我的角度来看,这两个概念之间的关系是:策略模式利用Java等语言中可用的多态性的力量来实现其意图,而多态性本身可以被视为一种模式。

    例如,考虑GoF书中的这句话:

    如果我们假设使用过程语言,我们可能会包含设计 称为“继承”、“封装”和“多态”的模式。

    只是我们很少将多态性视为一种模式,首先是因为它意味着许多事情,因为它在不同语言中的实现方式不同,而且还因为它通常表现为某种形式的语言特征。

    杰森·麦克·史密斯(Jason Mc C.Smith)在其著作《元素设计模式》(Elemental Design Patterns)中对GoF的上述引用进行了评论:

    模式是独立于语言的概念;他们形成并成为 具体的解决方案 具有给定的一组语言特征和结构的语言〔…〕 这意味着谈论“Java设计”有点奇怪 pattern”、“C++设计模式”、“Websphere设计模式”等, 尽管我们都这样做。这是对 我们真正的意思或应该是什么: Java、C++、WebSphere等,无论语言或API如何。

    因此,正如您所看到的,您正在从Java实现的角度思考Strategy模式,但在其他语言范例中,这种模式可能以不同的方式实现,可能根本不使用继承,例如,在纯函数式编程语言中,这最肯定是使用 high order functions function composition .

    因此,这将是一种战略模式的实施,而无需诉诸 包涵体多态性 完全在函数组合策略中,我们可能仍然使用其他形式的多态性(例如参数化),但这不是策略模式的要求

    Q: 请给我举个例子,消除我的困惑。

    如上所述,在Java中,我们可能被迫使用包含多态性来实现一种策略模式,但正如上面所解释的,模式不是属于特定语言的东西,因此如果我们将策略模式视为一个生活在任何语言边界之外的概念,那么您将很容易看到其他语言以不同的方式实现这一点。

    在一些假设的函数语言中,我可能有一个从文件中读取一些数据的函数,可能文件是加密的,您需要提供解密策略:

    function readFile(path: String, decrypt: string -> string) {
        return decrypt(loadFromDisk(path));
    }
    

    还有那个 decrypt argument是一个服务于策略模式目的的函数,它封装了一个可互换的算法。

    现在你可以了

    readFile("customers.txt", aes)
    readFile("finance.txt", blowfish)
    

    哪里 aes blowfish 是解密函数策略。

    像这样工作的语言有几十种,SML、Haskell、JavaScript等。

        6
  •  3
  •   Herman Wilén    9 年前

    首先多态性可能意味着两种不同的东西。最常见的多态性是指多态类型。然而,您要求的是模式。

    多态代码可以在每次运行时改变自身,而代码的功能保持不变。一个简单的例子是做1+3=4而不是5-1=4。两者都使用不同的代码获得相同的结果。这对于不希望被识别的代码(即计算机病毒或密码)非常有用。

    另一方面,策略模式使用一系列可以互换的算法。这可能在翻译文本时使用。首先,一些代码决定了语言。如果语言是瑞典语或西班牙语,则文本将由同一家族的不同函数translateSwedish()或translatePanish()处理。

    把事情凑起来。多态代码使用不同的代码实现相同的结果。而Strategy使用不同的代码以获得更好的结果。

        7
  •  2
  •   Joshua Byer    9 年前

    考虑一下这个

    我们有动物和一个策略模式对象来描述它们如何移动。。。 例如

    飞行/游泳/散步

    考虑到使用这些方法的动物数量众多(即数千种不同的动物在飞行),我们需要对许多不同的动物使用相同的代码。该代码应该只存在于一个地方,这样就可以很容易地进行更改,并且不会占用任何多余的空间。

    在本例中,简单的多态性方法将导致大量代码重复。一种更复杂的方法是在动物和知更鸟之间设置一个中间类,但它没有考虑到动物的移动方式并不是真正的定义。此外,动物可能有其他策略对象,它们不能通过中间类都变成多态的。

        8
  •  2
  •   Omar Ayala    9 年前

    多态性的一个定义是向不同类型的实体提供单一接口。

    考虑到这一点,假设您有一个bird接口,并且您的所有bird类都必须实现laysEggs()方法,这没什么大不了的。当你继续编写你的鸟天堂程序时,你现在添加了fly(),并意识到企鹅和猕猴桃的重载和重写是不必要的,因为在现实生活中它们不会飞,但你仍然必须实现这个方法。当你面对鸵鸟和其他不会飞的动物时,这可能会变得乏味和毫无意义。在添加方法swim()时更糟糕,因为会游泳的鸟更少。正如您可能已经知道的,策略模式解决了这个问题。

    用蹩脚的术语来说,你可以把多态性看作是一个实践的集合体,而战略模式是特定案例的最佳实践。示例:当需要在运行时(通过可互换的算法)选择算法的行为时,将使用策略模式。虽然通过策略模式实现的任何事情基本上都是通过多态性实现的,但如果不了解策略模式,这将使您面临重新发明轮子的问题来解决这个特定问题。总之,即使一个基于另一个,它们也非常不同。 我会让你看Ender Muab'Dib代码,因为它已经很好地解释了,如果你仍然想从我这里得到代码示例,请问我,加油,希望我能帮助你。

        9
  •  2
  •   Ravindra babu    7 年前

    多态性是一种原则,策略是一种设计模式

    来自oracle文档 page

    多态性的字典定义是指生物学中的一个原则,其中一个生物体或物种可以有许多不同的形式或阶段。这一原则也适用于面向对象编程和Java语言等语言。类的子类可以定义自己独特的行为,但也可以共享父类的一些相同功能。

    多态性可以在编译时(方法重载)和运行时(方法重写)实现。

    Strategy_pattern

    1. 定义了一系列算法,
    2. 封装每个算法,以及
    3. 使算法在该族中可互换。

    策略可以使用运行时多态性原理来实现所需的功能。

    策略模式的URL图中还有一个名为Context的组件。 请参阅以下SE帖子:

    Real World Example of the Strategy Pattern

    Does this Java Strategy pattern have a redundant Context class?

    几篇更有用的文章:

    strategy 通过资源制造

        10
  •  0
  •   Ahmad    4 年前

    以下是简洁的回答:

    1. 多态性是 面向对象编程。
    2. 策略模式是一种独立于语言的模式,可以由所有人实现 编程语言范例,如命令式、函数式和 面向对象。

    因此,如果要使用Java(即OOP)实现Strategy模式,那么只需要使用多态性。

    换句话说,Strategy模式是多态性的多种形式之一。