设计模式之策略模式

  |  


前言

​ 一直没有养成写博客的习惯,很早就打算通过设计模式来开始博客之旅,后面因为上半年找工作对并发知识缺乏。就学了一阵子以并发相关内容开始写博客了,现在才写了几篇,之后会继续完善。现在在阅读《Head First设计模式》,刚好博客记录下学习过程。都知道设计模式在OO编程中很重要,理解和在实际中运用完全不是同一回事,但是在运用之前我们起码的先学会不是吗?

定义

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

使用场景

​ 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时,策略模式能够很好地应对变化;

示例

​ 下面我们将通过一个烹饪鸡的例子来更好的理解(至于为什么是烹饪鸡,你懂得);

正常实现

首先我们定义一个Person接口类

这个person有很多技能(吃饭睡觉打豆豆),我们不关注,本场景下我们用到的只有一个cookieChicken(烹饪鸡肉)

1
2
3
4
5
//人物类
public interface Person {
//烹饪鸡肉
void cookingChicken();
}

接下来本篇博客主角陈师傅登场

1
2
3
4
5
6
7
//陈师傅
public class MasterChen implements Person {
@Override
public void cookingChicken() {
System.out.println("辣子鸡");
}
}

陈师傅(也喜欢吃鸡肉),尤其是辣子鸡,所以他烹饪鸡的做法,第一种就学的辣子鸡

好,接下来我们把鸡肉交给陈师傅

1
2
3
4
public static void main(String[] args) {
Person masterChen = new MasterChen();
masterChen.cookingChicken();
}

天天吃一种菜总是会腻的,尽管喜欢吃,陈师傅依稀记得在重庆旅游的时候,吃过一次正宗的重庆鸡公煲,味道很是美味,话不多话,就是干。陈师傅开始学重庆鸡公煲的做法,不久后出师。

现在我们构造的陈师傅应该怎么样适应变化呢?恩 一开始肯定都是这么想的,我们改造下

1
2
3
4
5
//人物类
public interface Person {
//烹饪鸡肉
void cookingChicken(String type);
}

人物类中烹饪鸡肉我们增加一个type区分不同的做法

1
2
3
4
5
6
7
8
9
10
11
12
//陈师傅
public class MasterChen implements Person {
@Override
public void cookingChicken(String type) {
if(type.equals("辣子鸡")){
System.out.println("辣子鸡");
}else if(type.equals("重庆鸡公煲")){
System.out.println("重庆鸡公煲");
}

}
}

现在的陈师傅可以通过type,来用不同的烹饪方式烹饪鸡肉

1
2
3
4
5
public static void main(String[] args) {
Person masterChen = new MasterChen();
masterChen.cookingChicken("辣子鸡");
masterChen.cookingChicken("重庆鸡公煲");
}

恩,这样我们的目的的确达到了,偶然的一次机会,陈师傅到广州沟通学习,并学会了白切鸡的做法。

为了适应变化,我们又要修改我们构造的陈师傅。不过在修改之前,我们思考一个问题,每次陈师傅新学一种烹饪鸡肉的做法,我们就要修改我们构造的陈师傅,这是不是不合适呢?在OO编程中,我们一直主张对扩展开发,对修改关闭。我们此刻的做法就违背这个原则。在实际生产中我们应该也是尽量做到新增功能不影响原有的功能。

此刻,策略模式隆重登场,在这个场景中,不断变化的是烹饪鸡的做法,我们可以把其看做策略模型中的算法抽离出来。以后增加算法都不影响原有的功能。

策略模式登场

类图

改造

人物类改造

1
2
3
4
5
6
7
8
9
10
public abstract class Person {
//烹饪鸡肉的行为
CookChicken cookChicken = null;
//烹饪鸡肉
abstract void cookingChicken();

public void setCookChicken(CookChicken oneCookChicken){
cookChicken =oneCookChicken;
}
}

这里我们将人物类由接口改成了抽象类,将烹饪鸡肉这一做法抽离成行为的方式(面对接口编程不一定是指完全面对Interface编程,关键在于多态。利用多态,程序可以针对超类型编程,某些场景下抽象类比接口更合适)

烹饪鸡肉行为类

1
2
3
public interface CookChicken {
void cooking();
}

同时,针对辣子鸡,和白切鸡我们定义了两个实现类

辣子鸡:

1
2
3
4
5
6
public class SpicyChicken implements CookChicken {
@Override
public void cooking() {
System.out.println("辣子鸡");
}
}

白切鸡:

1
2
3
4
5
6
public class WhiteCutChicken implements CookChicken {
@Override
public void cooking() {
System.out.println("白切鸡");
}
}

重庆鸡公煲:

1
2
3
4
5
6
public class ChongqingChicken implements CookChicken {
@Override
public void cooking() {
System.out.println("重庆鸡公煲");
}
}

最后就是经过改造的陈师傅,此刻的陈师傅能够灵活运用多种烹饪鸡肉的做法

1
2
3
4
5
6
7
8
9
10
11
12
public class MasterChen extends Person {

public MasterChen() {
cookChicken = new SpicyChicken();
}

@Override
public void cookingChicken() {
//默认用陈师傅最熟悉的辣子鸡来实例化
cookChicken.cooking();
}
}
1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
Person masterChen = new MasterChen();
masterChen.cookingChicken();
masterChen.setCookChicken(new ChongqingChicken());
masterChen.cookingChicken();
masterChen.setCookChicken(new WhiteCutChicken());
masterChen.cookingChicken();

}
}

结果如下

1
2
3
辣子鸡
重庆鸡公煲
白切鸡

经过我们的改造,我们能在运行时通过setCookChicken在陈师傅工作期间,动态用不同的烹饪手法,做出不同的鸡肉(辣子鸡、重庆鸡公煲、白切鸡)。今后即时陈师傅各种深造,学习更多地烹饪鸡肉的做法。我们也只需要实现更多地烹饪行为实现类,无需对陈师傅进行各种改造。

这就是策略模式通过将某些相同系列算法抽离程序,在组合进去,使得系统更具有弹性

总结

最后我们在回顾一次策略模式的定义,是不是理解更深刻了呢

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

参考资料:《Head First 设计模式》

文章目录
  1. 1. 前言
  2. 2. 定义
  3. 3. 使用场景
  4. 4. 示例
    1. 4.1. 正常实现
    2. 4.2. 策略模式登场
      1. 4.2.1. 类图
    3. 4.3. 改造
  5. 5. 总结
|
本站总访问量 载入天数...载入时分秒...