【设计模式】策略模式

问题背景

image-20201010183929742

有父类duck,实现了quack(叫)和swim(游泳)两个方法

预留了display方法给子类实现

子类可能有多种,现在假设只有MallardDuck和RedheadDuck

需求:fly()

现在需要给鸭子实现fly(飞)方法

解决方法1:在父类中实现

image-20201010184247320

在父类中添加fly方法给子类继承

变化1:部分Duck不能fly

image-20201010184410279

如果仍使用继承,那么本不该fly的Duck也能访问到fly接口

解决方法2:在子类中进行重写

image-20201010184622899

缺点:

这种方法的缺点:(ABDF?)

image-20201010184747359

且在未来的维护过程中,如果需要添加新的类,就必须反复检查所有接口并可能重写部分接口

解决方法2:用接口实现

image-20201010185152430

缺点:

如果未来出现需要对【fly】这个行为进行修改,比如修改fly的速度,那么可能需要对已有的所有类都要进行修改

而且使用接口的方法本身需要在每个子类中附加实现,这样产生了非常多的重复和冗余的代码

java接口不具有实现代码,所以集成接口无法达到代码的复用。这意味着无论何时需要修改某个行为,必须得往下追踪并在每一个定义此行为的类中修改它,可能会造成新的错误。

策略模式方法

  • 把会变化的部分取出并封装起来,好让其他部分不受到影响

  • 以下的用词【接口】既可以指java中的interface,也可以指abstract class,只是一个概念性接口

  • 如果每次新的需求依赖,都会使某些方面的代码发生变化,那么就可以确定,这部分的代码需要被抽出来,和其他稳定的代码有所区分

    image-20201010190515833

将变化的代码抽取出来

image-20201010190551748

将经常变化的代码,在本例中指fly和quack,抽取出来,独立为两个接口:FlyBehavior和QuackBehavior

具体每种实现方式,可以由继承他们的子类来实现,而Duck类中只需要留下调用Behavior的接口即可

优点:
  • 这样的设计,可以让fly和quack的动作被其他的对象复用,因为这些行为已经与Duck类无关了(例如:在可以发出鸭叫的机器中可以调用quack的动作,但是机器不是Duck类)
  • 我们可以新增一些行为,不会影响到已有的类,以及使用现有行为的类
现在的Duck类

image-20201010192220693

  • 将Duck类中经常变化的行为抽象为一个接口,即flyBehavior和quackBehavior

  • 用perform行为来替代原来的行为,即performQuack和performFly替代原来的quack和fly

  • 每个子类实例化时,都可以指定该子类对应的行为

    image-20201010192416055

  • 也可以为子类预留setter方法,从而在运行中改变其行为方式

    image-20201010192538527

    在运行过程中,子类可以动态的调用setter方法来改变其行为方式

    image-20201010192648612

总览UML图

image-20201010192806233

设计原则

    1. 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起
    1. 针对接口编程,而不是针对实现编程
    1. 多用组合,少用继承

策略模式

  • Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it

    翻译:策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

  • Use the Strategy pattern when

    • many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.

    • you need different variants of an algorithm. For example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms.

    • an algorithm uses data that clients shouldn’t know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.

    • a class defines many behaviors, and these appearas multiple conditional statements in its operations.
      Instead of many conditionals, move related conditional branches into their own Strategy class.

    翻译:当出现以下情况时可以使用策略模式:

    • 许多相关类仅在它们的行为上有所不同。策略提供了一种方法来配置具有多种行为之一的类。

    • 你需要一个算法的不同变体。例如,您可以定义反映不同空间/时间权衡的算法。当这些变体被实现为算法的类层次结构时,可以使用策略。

    • 算法使用客户端不应该知道的数据。使用Strategy模式可以避免暴露复杂的、特定于算法的数据结构。

    • 一个类定义了许多行为,这些行为在它的操作中表现为多个条件语句。将相关的条件分支移动到它们自己的策略类中,而不是使用许多条件语句。

  • Consequences

    • Families of related algorithms. Hierarchies of Strategy classes define a family of algorithms or behaviors for contexts to reuse. Inheritance can help factor out common functionality of the algorithms.
    • An alternative to subclassing.
    • Strategies eliminate conditional statements.
    • A choice of implementations. Strategies can provide different implementations of the same behavior. The client can choose among strategies with different time and space trade-offs.
    • Clients must be aware of different Strategies. The pattern has a potential drawback in that a client must understand how Strategies differ before it can select the appropriate one. Clients might be exposed to implementation issues.
    • Communication overhead between Strategy and Context.
    • Increased number of objects.

    翻译:使用策略模式的影响:

    • 相关算法族。策略类的层次结构定义了一系列要重用的上下文的算法或行为。继承可以帮助提取出算法的常见功能。
    • 子类化的替代方法。
    • 策略消除了条件语句。
    • 实现的选择。策略可以为相同的行为提供不同的实现。客户可以选择不同的时间和空间权衡策略。
    • 客户必须了解不同的策略。该模式有一个潜在的缺点,即客户必须了解策略之间的差异,然后才能选择合适的策略。客户端可能会遇到实现问题。
    • 策略和上下文之间的沟通开销。
    • 增加的对象数量。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值