白话策略模式
策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
以上是百度百科对于策略模式的定义,估计不熟悉的人读完这句话依然是云里雾里,并没有什么卵用,希望可以通过这篇文章给策略模式提供一个更加具象化的描述。
设计模式,说成白话,就是软件开发的套路。现在我们在开发过程中遇到的问题,有些在多年前就困扰过其他前辈,而他们在无数次的实践中总结出了一个个解决问题的方法,也就是我们所知道的设计模式。
在软件开发的过程中,大多数开发人员都经历过需求不断变更的过程,而这个可以说是开发人员最厌恶的事,而这正是策略模式的使用场景之一。
既然要具象化描述,肯定需要将其放到实际情况中来看。这里我们借用《 Head First 设计模式》中的例子进行说明,公司有一款鸭子游戏,鸭子这一部分呢,有一个 Duck 的超类和 N 个子类(绿头鸭、机械鸭、石头鸭 ...),现在要求让鸭子飞起来。
各种鸭子先来想想有什么方法可以解决这个问题?
- 每个类添加自己的方法
- 子类继承父类方法,然后覆盖具体实现
- 子类实现接口
以上可能就是第一时间想到的方法,大家可以实践一下,这几种方法都存在着一个问题:大量的冗余代码。目前仅生物学上已知的鸭科动物就有150多种,还有无数非生物学上的鸭子(比如上边的石头鸭),如果都放到这个例子中,每个类或者说绝大多数类都要写好自己的实现,毕竟每种鸭子飞的形式不一样,甚至有的不会飞。
既然要解决这个问题,我们先看下这个问题所在,要让不同的鸭子飞起来,这里最大的问题就是不同种类的鸭子飞的形式或者方法是不一样的,换句话说,类的行为在子类中是不断变化的。
针对这个问题,我们的方法就是:将不断变化的行为独立出来,在运行过程中动态的修改它。独立出来的行为我们可以称之为策略,而这个方法就是策略模式。
策略模式既然策略模式能够解决这个问题,那么它是怎么解决的呢?核心思想就是整合类的行为,之后再动态的进行设定。实践过程如下:
- 创建行为接口,整合类的行为。
public interface FlyBehavior {
void fly();
}
- 创建行为接口的实现类,实现具体的行为。这里我们创建两个。
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
//不会飞
System.out.println("fly no way");
}
}
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
//用翅膀飞
System.out.println("fly with wings");
}
}
- 在父类 Duck 中添加行为。
public class Duck{
protected FlyBehavior flyBehavior;
public void performFly() {
flyBehavior.fly();
}
public FlyBehavior getFlyBehavior() {
return flyBehavior;
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
}
- 动态修改类的行为。
Duck duck = new Duck();
duck.setFlyBehavior(new FlyWithWings());
duck.performFly();
duck.setFlyBehavior(new FlyNoWay());
duck.performFly();
以上是策略模式的应用过程,修改类的行为时,Duck 可以替换为任何一个子类,FlyBehavior 也可以设置任何一个实现类。通过这个方法,我们可以保证飞行的行为不需要重复,我们只需要将其归为几类即可,而且后续增加 Duck 子类的时候,我们并不需要额外增加飞行行为。
简而言之,策略模式就是将变化的内容封装为一个个策略,从而将其与其他不变的内容进行分离,之后在使用过程中进行动态改变,达到修改策略时不影响其调用者的目的。至此我们已经尝试过了策略模式的初步应用,而熟练掌握一种模式最好的方法是实践,建议重构以前做过的项目,将策略模式引入其中。
以上是我的一点心得体会,希望这篇文章可以为需要的人提供一点帮助。