前言
大家好,我是练习两年半的Java练习生,最近阅读了《深入浅出设计模式(中文版)》,学习了各种设计模式,所以想出一个专栏和大家分享一下!
如果大家觉得文章还可以,欢迎关注点赞!后续还会陆续更新!!
定义
策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时动态地改变对象的行为。该模式定义了一系列算法,将每个算法都封装起来,使它们可以相互替换,并且让算法的变化不会影响到使用算法的客户端。
类图
- Strategy(策略) : 定义了支持具体策略的公共接口
- Context(上下文):持有策略对象,并调用其算法。提供一个set方法,将策略的选择权交给用户,用户可以自行选择所需要的算法
应用
需求
Joe上班的公司做了一套相当成功的模拟鸭子游戏:SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边弧
呱叫。此系统的内部设计使用了标准的00技术,设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。
现在需要让鸭子有些能飞,有些鸭子不能飞。
分析
错误解法
明显的我们可以继续使用继承,在Duck类里面增加一个fly()方法。然后每个具体的鸭子类覆盖fly()方法,实现不同的行为。
但这种方法似乎不是很好,因为后面如果增加其他的行为,我们需要不断检查每个鸭子类里面的fly方法,并修改成不同的行为。
使用策略模式
我们可以发现,fly飞行这个行为是经常需要改变的,因此我们应该封装这个变化,使每个鸭子在增加一种fly行为时,不需要改变原有的代码。
因此,我们可以将fly这个行为定义成一个接口FlyBehavior,提供不同的fly实现,将这个接口在Duck中使用,即Duck现在依赖FlyBehavior接口,我们修改行为时,只需要用set方法改变Duck里面的Fly策略,而无需改变Duck子类的代码。
实现
类图
代码
public abstract class Duck {
private FlyBehavior flyBehavior = new FlyWithWings();//这里默认实现鸭子是会飞的,用户可以修改
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void performFly(){
flyBehavior.fly();//这里Duck不处理fly行为,而是委托给flyBehavior对象
}
public void swim(){
System.out.println("鸭子游泳");
}
public void display(){
System.out.println("鸭子表现");
}
}
public interface FlyBehavior {
void fly();
}
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("用翅膀飞行");
}
}
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("不能飞行");
}
}
public class MallardDuck extends Duck{
}
public class RedHeadDuck extends Duck{
}
public class StrategyTest {
public static void main(String[] args) {
Duck mallardDuck = new MallardDuck();
Duck redHeadDuck = new RedHeadDuck(); // 红头鸭默认能飞
mallardDuck.setFlyBehavior(new FlyNoWay());//野鸭不能飞
redHeadDuck.performFly();
mallardDuck.performFly();
}
}
问题
如何将创建一只有火箭动力的鸭子?尝试一下吧!
总结
以上就是今天要讲的内容,本文仅仅简单介绍了设计模式中最常见的模式:策略模式,策略模式定义了一系列的算法,通过接口,使得它们可以互相替换,实现了解耦合。后续的模板模式与这个很类似,到时会讲两者的区别,敬请期待!