设计模式1-策略模式

    xiaoxiao2023-11-30  185

    1.场景问题解决

    1.1 场景描述

    模拟鸭子游戏,鸭子能叫,能游泳,鸭子还有各种品种,绿头鸭,红头鸭.

    1.2 OO设计

    类图如下:

    鸭子抽象类 Duck---->叫声和游泳是普通方法,display是抽象方法,继承的类要实现该方法 public abstract class Duck { public Duck() { } public void Quack() { System.out.println("~~gaga~~"); } public abstract void display(); public void swim() { System.out.println("~~im swim~~"); } } GreenHeadDuck 绿头鸭 public class GreenHeadDuck extends Duck { @Override public void display() { System.out.println("**GreenHead**"); } } RedHeadDuck 红头鸭 public class RedHeadDuck extends Duck { @Override public void display() { System.out.println("**RedHead**"); } } main public class StimulateDuck { public static void main(String[] args) { GreenHeadDuck mGreenHeadDuck = new GreenHeadDuck(); RedHeadDuck mRedHeadDuck = new RedHeadDuck(); mGreenHeadDuck.display(); mGreenHeadDuck.Quack(); mGreenHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.Quack(); mRedHeadDuck.swim(); } }

    1.3 需求变动,需要增加飞(fly())的功能

    鸭子抽象类 Duck---->叫声和游泳是普通方法,display是抽象方法,继承的类要实现该方法 public abstract class Duck { public Duck() { } public void Quack() { System.out.println("~~gaga~~"); } public abstract void display(); public void swim() { System.out.println("~~im swim~~"); } public void Fly() { System.out.println("~~im fly~~"); } } GreenHeadDuck 绿头鸭–继承默认就有了Fly功能 public class RedHeadDuck extends Duck { @Override public void display() { System.out.println("**RedHead**"); } } RedHeadDuck 红头鸭 --没有fly功能还要继承覆盖 public class RedHeadDuck extends Duck { @Override public void display() { System.out.println("**RedHead**"); } public void Fly() { System.out.println("~~I cannot fly~~"); } } main public class StimulateDuck { public static void main(String[] args) { GreenHeadDuck mGreenHeadDuck = new GreenHeadDuck(); RedHeadDuck mRedHeadDuck = new RedHeadDuck(); mGreenHeadDuck.display(); mGreenHeadDuck.Fly(); mGreenHeadDuck.Quack(); mGreenHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.Quack(); mRedHeadDuck.swim(); mRedHeadDuck.Fly(); } }

    1.4 带来问题

    带来问题: 在的抽象父类中增加了fly()的方法,那么所有的子类都有了fly()的方法,如果RedHeadDuck鸭子不能飞翔,则还要覆盖fly()方法不让fly();

    **继承的问题:**对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应

    当方法越来越多的时候,个性化越来越多的时候,那么各个子类需要覆盖的方法越来越多。

    2.用设计模式改进

    2.1 分析

    2.1.1 需要新的设计方式,应对项目的扩展性,降低复杂度:

    1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现; 2)鸭子哪些功能是会根据新需求变化的?叫声、飞行…

    2.1.1 新增行为接口

    接口:

    public interface FlyBehavior{ void fly(); } public interface QuackBehavior{ void quack(); };

    好处:新增行为简单,行为类更好的复用,组合更方便。既有继承带来的复用好处,没 有挖坑

    2.2 重新设计类图

    2.3 重新设计代码

    Duck public abstract class Duck { FlyBehavior mFlyBehavior; QuackBehavior mQuackBehavior; public Duck() { } public void Fly() { mFlyBehavior.fly(); } public void Quack() { mQuackBehavior.quack(); } public abstract void display(); public void SetQuackBehavoir(QuackBehavior qb) { mQuackBehavior = qb; } public void SetFlyBehavoir(FlyBehavior fb) { mFlyBehavior = fb; } public void swim() { System.out.println("~~im swim~~"); } } FlyBehavior接口及实现 //FlyBehavior接口 public interface FlyBehavior { void fly(); } public class BadFlyBehavior implements FlyBehavior{ @Override public void fly() { System.out.println("--BadFly--"); } } public class GoodFlyBehavior implements FlyBehavior{ @Override public void fly() { System.out.println("--GoodFly--"); } } public class NoFlyBehavior implements FlyBehavior{ @Override public void fly() { System.out.println("--NoFly--"); } } QuackBehavior接口及实现 public interface QuackBehavior { void quack(); }; public class GaGaQuackBehavior implements QuackBehavior{ @Override public void quack() { System.out.println("__GaGa__"); } } public class GeGeQuackBehavior implements QuackBehavior { @Override public void quack() { System.out.println("__GeGe__"); } } public class NoQuackBehavior implements QuackBehavior { @Override public void quack() { System.out.println("__NoQuack__"); } } Duck及Duck实现 public abstract class Duck { FlyBehavior mFlyBehavior; QuackBehavior mQuackBehavior; public Duck() { } public void Fly() { mFlyBehavior.fly(); } public void Quack() { mQuackBehavior.quack(); } public abstract void display(); public void SetQuackBehavoir(QuackBehavior qb) { mQuackBehavior = qb; } public void SetFlyBehavoir(FlyBehavior fb) { mFlyBehavior = fb; } public void swim() { System.out.println("~~im swim~~"); } } public class GreenHeadDuck extends Duck { public GreenHeadDuck() { mFlyBehavior = new GoodFlyBehavior(); mQuackBehavior = new GaGaQuackBehavior(); } @Override public void display() { System.out.println("**GreenHead**"); } } public class RedHeadDuck extends Duck { public RedHeadDuck() { mFlyBehavior = new BadFlyBehavior(); mQuackBehavior = new GeGeQuackBehavior(); } @Override public void display() { System.out.println("**RedHead**"); } } Main public class StimulateDuck { public static void main(String[] args) { Duck mGreenHeadDuck = new GreenHeadDuck(); Duck mRedHeadDuck = new RedHeadDuck(); mGreenHeadDuck.display(); mGreenHeadDuck.Fly(); mGreenHeadDuck.Quack(); mGreenHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.Fly(); mRedHeadDuck.Quack(); mRedHeadDuck.swim(); mRedHeadDuck.display(); mRedHeadDuck.SetFlyBehavoir(new NoFlyBehavior()); mRedHeadDuck.Fly(); mRedHeadDuck.SetQuackBehavoir(new NoQuackBehavior()); mRedHeadDuck.Quack(); } }

    3.设计模式总结

    3.1 定义

    策略模式: 分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设 定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为 算法的变化独立于算法的使用者。

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

    3.2 分析思路

    1、分析项目中变化部分与不变部分,把他们独立出来,不要和那些不需要变化的代码混在一起2、多用组合少用继承;用行为类组合,而不是行为的继承。更有弹性3、设计模式有没有相应的库直接使用?有些库或框架本身就用某种设计模式设计的4、如果找不到适用的模式怎么办

    3.3 总结设计原则

    设计原则1:分析项目中变化部分与不变部分,把他们独立出来,不要和那些不需要变化的代码混在一起设计原则2:针对接口编程,而不是针对实现编程设计原则3:多用组合,少用封装

    4. 设计模式使用场景及注意

    5.参考文章

    读headFirst设计模式 - 策略模式

    13种UML简介、工具及示例

    内容总计于HeadFirst设计模式及相关视频

    最新回复(0)