策略模式

1|0基本介绍

策略模式的策略,该怎么理解呢?在我看来,就是在面对不同的场景,采取不一样的处理方式
策略模式属于行为型模式,大多应用于动态在一个对象的多种行为进行切换的场景。
意图:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,以避免在多种算法相似的场景下,使用过多的 if...else 所带来的复杂和难以维护
注意:当一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题
 
假设有一家游戏公司,委托我们开发一款模拟鸭子池塘的游戏,该公司的主要产品是一种可以模拟展示多种会游泳和嘎嘎叫的鸭子的游戏,它们要求在设计鸭子时尽量贴近生活,保持真实性。
 
他们的最初始的设计如下:

鸭子的抽象类

public abstract class Duck { public Duck() {} public abstract void display();// 显示鸭子信息 public void quack() { System.out.println("鸭子嘎嘎叫"); } public void swim() { System.out.println("鸭子会游泳"); } public void fly() { System.out.println("鸭子会飞翔"); } }

 
北京鸭

public class PekingDuck extends Duck { @Override public void display() { System.out.println("北京鸭"); } /** * 由于北京鸭不会飞翔,因此需要重写fly */ @Override public void fly(){ System.out.println("北京鸭不会飞翔"); } }

 
玩具鸭

public class ToyDuck extends Duck { @Override public void display() { System.out.println("玩具鸭"); } @Override public void quack() { System.out.println("玩具鸭不能叫~~~"); } @Override public void fly() { System.out.println("玩具鸭不会飞翔~~"); } }

 
野鸭

public class WildDuck extends Duck { @Override public void display() { System.out.println("这是野鸭"); } }

 
利用继承来复用鸭子的各个行为,初衷是好的,但是没有真正将鸭子的各个行为拆分,只是简单的复用,就会有很多问题。
当我们需要新添加一类鸭子,若其父类的抽象方法不满足当前对象时,我们就需要重写以覆盖父类的抽象方法,这就违背了里式替换原则且扩展性欠缺。
 

2|0策略模式

刚刚我们也说了,策略模式主要应用 动态在一个对象的多种行为进行切换的场景
那我们开始重新构建模拟鸭子的这款游戏吧,我们想一想能不能把鸭子的各种行为抽出来再跟鸭子进行组合, 这样在面对不同的鸭子时进行组装即可
 

鸭子的抽象类

public abstract class Duck { //属性,策略接口 FlyBehavior flyBehavior; public Duck() {} public abstract void display();// 显示鸭子信息 public void quack() { System.out.println("鸭子嘎嘎叫"); } public void swim() { System.out.println("鸭子会游泳"); } public void fly() { if(flyBehavior != null){ flyBehavior.fly(); } } }

 
飞行行为

public interface FlyBehavior { void fly(); }

 
行为-飞的好

public class GoodFlyBehavior implements FlyBehavior { @Override public void fly() { System.out.println("飞翔技术高超"); } }

 
行为-飞的一般

public class NormalFlyBehavior implements FlyBehavior { @Override public void fly() { System.out.println("飞翔技术一般"); } }

 
行为-不会飞

public class NoFlyBehavior implements FlyBehavior { @Override public void fly() { System.out.println("不会飞翔"); } }

 
北京鸭

public class PekingDuck extends Duck { public PekingDuck(){ //给鸭子赋予飞的一般的行为 flyBehavior = new NormalFlyBehavior(); } @Override public void display() { System.out.println("北京鸭"); } }

 
野鸭

public class WildDuck extends Duck { public WildDuck() { //给鸭子赋予飞的好的行为 flyBehavior = new GoodFlyBehavior(); } @Override public void display() { System.out.println("这是野鸭"); } }

 
玩具鸭

public class ToyDuck extends Duck { public ToyDuck(){ //给鸭子赋予不会飞的行为 flyBehavior = new NoFlyBehavior(); } @Override public void display() { System.out.println("玩具鸭"); } @Override public void quack() { System.out.println("玩具鸭不能叫~~~"); } }

 
从上述的例子我们看出,将鸭子的各个行为组合到不同的鸭子中去,既增加了系统的弹性,也满足了每个鸭子的特点。
鸭子会不会飞,飞的好不好根据不同的策略制定。
综上: 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
 

3|0JDK-Arrays的应用

在jdk中, Arrays 的Comparator 就实现了策略模式

public class Arrays { public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } } }
public interface Comparator<T> { int compare(T o1, T o2); }

 
我们测试一下:

public class TestStrategy { public static void main(String[] args) { // 数组 Integer[] data = { 9, 1, 2, 8, 4, 3 }; // 实现降序排序,返回-1放左边,1放右边,0保持不变 // 说明 // 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..} // 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象 // 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式 Comparator<Integer> comparator = new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { if (o1 > o2) { return -1; } else { return 1; } }; }; // 说明 /* * public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) * { sort(a); //默认方法 } else { if (LegacyMergeSort.userRequested) * legacyMergeSort(a, c); //使用策略对象c else // 使用策略对象c TimSort.sort(a, 0, a.length, * c, null, 0, 0); } } */ // 方式1 Arrays.sort(data, comparator); System.out.println(Arrays.toString(data)); // 降序排序 // 方式2- 同时lambda 表达式实现 策略模式 Integer[] data2 = { 19, 11, 12, 18, 14, 13 }; Arrays.sort(data2, (var1, var2) -> { if (var1.compareTo(var2) > 0) { return -1; } else { return 1; } }); System.out.println("data2=" + Arrays.toString(data2)); } }

__EOF__

本文作者丁可乐
本文链接https://www.cnblogs.com/dwlovelife/p/13355836.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   丁可乐  阅读(591)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示