策略模式——从鸭子入手

一个鸭子类,子类有绿头鸭和红头鸭。

每个鸭子都会叫,也会游泳,所以由超类来处理这些共同的东西。而display()方法是用来显示,更加直观的体现各部分的关系。

当涉及维护时,为了复用而使用继承,问题往往更大。

如果我们在Duck类中加一个fly()飞的方法,结果会怎么样?

由于考虑不周,在Duck类中增加了fly(),这样ToyDuck玩具鸭子也继承了这个方法。可是事实上玩具鸭子是飞不起来的,那怎么办?类似的问题是,玩具鸭子只会吱吱地响,而不会向红头鸭那样呱呱的叫。

这时,我们就要用“覆盖”了,将ToyDuck玩具鸭中的fly()方法覆盖掉,变成什么也不做,类似的,将quack()方法覆盖为吱吱叫。

到这里,好像勉强是可以完成任务了。但当一个新的鸭子子类出现的话,我们都要考虑它是不是能飞,是不是能叫,是怎样飞的,怎样叫的。可见,这样的实现方法并不能一劳永逸。

这时,我们可以考虑将一些容易或可能经常发生变化的一些方法,如fly,quack,从Duck抽象类中取出来,放到一个接口中,然后让会飞的绿头鸭、红头鸭去实现这个接口,而玩具鸭子就不去实现它了。

引入接口之后,事情就方便多了,可这样一来,各个子类的代码就没办法复用了。

找出可能变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

为了分开变化的和不变化的部分,需要建立两组类,一个是与fly相关的,一个是quack相关的,每组类各自实现各自的动作。我们将这两个行为从Duck类中分开,建立一组新类。

针对接口编程,而不是针对实现。

鸭子的子类将使用接口FlyBehavior和QuackBehavior所表示的行为,事实上的实现不会被绑死在鸭子的子类中。比如,玩具鸭子不能飞,这样的设计就可以在运行时动态的改变它的飞行行为。

整合之后的全图就变成了下面的样子:

由于精力有限,Duck中的部分地方没有说明。比如Duck类加了中两个实例变量 fly 和 quack,但并不影响理解。

对比之前商场打折的例子:

通过这两个例子,相信你会对策略模式有了更深入的理解。即使同样是理解了,总结与不总结收获差别蛮大的。

顺着书上的思路走,虽然挺麻烦的,也走了弯路,但正是这样,才能更深刻的理解那些原则、经验。剩下要做的就是结合代码再重新梳理一下思路了。

时间: 2024-12-29 12:00:29

策略模式——从鸭子入手的相关文章

head first 设计模式(-) 策略模式(鸭子)

目的:减少依赖 设计模式对应不同的需求,设计原则则代表永恒的灵魂,在实践中未必时刻遵守,但要时刻牢记. 1.依赖倒转原则(Dependence Inversion Principle) 2.接口隔离原则(Interface Segregation Principle) 3.里氏代换原则(Liskov Substitution Principle) 4.开闭原则(Open Close Principle) 5.迪米特法则(Demeter Principle) 6.合成复用原则(Composite

java设计模式之策略模式

策略模式 模拟鸭子游戏SimUDuck 设计原则: 找出应用中需要变化之处,把它们独立出来,不需要和那些变化的代码混在一起 设计原则: 针对接口编程,而不是针对实现编程 设计原则: 多用组合,少用继承 策略模式定义: 定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户 1 public class MiniDuckSimulator 2 { 3 public static void main(String[] args) 4 { 5 //绿头鸭 6 Duc

策略模式,我与你的三次相遇。

从商场打折到机房重构计算固定用户和临时用户的消费情况,再到现在的Duck,三次接触类策略模式,可见这是一个比较重要的模式. 在使用策略模式之前,首先要知道什么是策略模式?策略模式是干吗用的?策略模式有它的好处也必定存在一定的缺陷. 策略模式: 它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式其实就是用来封装算法的.当不同的行为堆砌在一个类中,就很难避免使用条件语句来选择合适的行为.我们就可以用策略模式,将这些行为封装在一个个独立的Stra

设计模式@第25章:策略模式

第25章:策略模式 一.编写鸭子项目,具体要求如下: 有各种鸭子(比如 野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如 叫.飞行等) 显示鸭子的信息 二.传统方案解决鸭子问题的分析和代码实现 传统的设计方案(类图) 代码实现-看老师演示 Duck 抽象类 package com.gjxaiou.strategy; public abstract class Duck { public Duck() { } public abstract void display();//显示鸭子信息 public

[一]Head First设计模式之【策略模式】(鸭子设计的优化历程)

public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } public abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void swi

对设计模式的总结之简单工厂与策略模式

前言 面向对象编程追求的本质-提高扩展性.可维护性.灵活性和复用性.合理利用面向对象6个原则,能够很好的达到要求.如何利用好就是至关重要的了,前人总结了23+个设计模式能够让初学者更容易学到其中的精髓,本文就说说我对本人对简单工厂模式.策略模式的见解. 简单工厂模式与策略模式 简单工厂模式 工作中,常常遇到需要做一个功能(鸭子),这个功能中含有可控个数的子操作功能(鸭子叫,鸭子跑,鸭子飞),而且子功能在不同的情况下处理方式又不相同(成年鸭子/小鸭子叫,成年鸭子/小鸭子跑,成年鸭子/小鸭子飞).我

java设计模式(六)策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们可以相互替换,让算法独立于使用它的客户而独立变化,具体应用场景如第三方支付对接不同银行的算法. 要点:1)抽象策略角色    2)具体策略角色:包装相关算法和行为 3)环境角色:持有一个策略类的引用,最终给客户端调用 1.抽象策略接口 public interface SwimmingStratege { public void swimming(); } 2.具体策略角色SwimmingWithFoot public class S

设计模式入门-策略模式&观察者模式

策略模式-strategy mod1:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起: 不同鸭子类型的飞行行为.鸣叫行为,会有不同的实现,可独立出来,和其他区分--区分变化的和不会变化的部分. mod2:针对接口编程,而不是针对实现编程: 鸭子子类使用接口表示行为,所以具体的实现不会绑死在鸭子的子类中,且可以在运行时改变行为. mod3:多用组合,少用继承: '有一个'比'是一个'更好,鸭子的具体行为可以委托给具体的行为类去处理,使用组合建立的系统有很大的弹性,不

策略模式--设计模式系列

今天我们写一个鸭子类,首先分析一下鸭子有哪些特征呢? 鸭子:会叫,会游水,会飞,外观 现在有个需求:分两种鸭子,一种是外观是绿头,一种是红头,写下看: class Duck: def quack(self): print('呱呱叫') def swim(self): print('我会游泳') def display(self):pass def fly(self): print('我会飞') class RedDuck(Duck): def display(self): print('我是红头