设计模式——策略模式(行为型模式)

时间:2021-01-21 22:00:34
前言:作为一个非计算机专业的编程爱好者,我们在面试的时候经常会遇到一些设计模式和数据结构的问题,当时我们可能会一脸黑人问号脸。exm?我能实现业务流程就好了,为啥还要懂这些。期初,我也感到不解,问了学计算机专业的同学,结果他们大多也不以为然,觉得没什么用,也只能讲个大概。但渐渐接触了设计模式后,再回去看以前的代码,就会感觉耦合度太高。如果面对修改,那我的代码就会不堪一击,陷入牵一发而动全身的尴尬地步。 所以我觉得学习一定的设计模式理念对编写更高质量的代码是有一定的帮助的。
在学习设计模式的时候,我也做也很多笔记,我会在这几天逐渐为大家整理和修改我之前的笔记,希望帮助学习设计模式的同学能够更加轻松的了解和学习设计模式。

点点滴滴的藏,集成了一大仓。——德国谚语


我们十分喜欢玩游戏,记得小学的时候有一款游戏叫“冒险岛”风靡了整个班。其中包含了很多的职业,有魔法师、弓箭手、勇士等等。今天我们来重温一下这款童年的游戏。
现在如果我们是盛大冒险岛的一名工程师,可能需要我们编写游戏里的角色的攻击行为,不同职业的角色具有不同的攻击特点,比如魔法师就是用法杖施法进行攻击,弓箭手就是用弓进行射箭攻击,勇士则是拿着剑进行攻击。来看看我们写的代码:
package com.example.vicky.strategypattern.StrategyPattern;

/**
* Created by Vicky on 2016/10/23.
*/
//封装不同武器攻击行为
public class Behavior {
public void attack(int type){
if (type==1){
//实现用法杖施法
System.out.print("用法杖施法");
}else if (type==2){
//实现用弓箭射击
System.out.print("用弓箭射");
}else if (type==3){
//实现用剑砍
System.out.print("用剑砍");
}
}
}
当我们要实例化攻击和使用攻击时的代码:
Behavior behavior=new Behavior();
behavior.attack(1);

这样的确实现了我们的业务逻辑,但冒险岛有一个特点就是不断会出新的职业,没个职业又会有各自特点的攻击方式,当之后不断推出海盗、飞侠...等等职业的时候,我们的attack方法中就需要不断的添加 else if 的判断语句, 这样就会造成我们的Behavior类的代码越来越多,不易于阅读,也不利于未来的拓展。
所以我们想到了使用策略的设计模式对Behavior这个类进行一定的改造, 把不同的攻击方式提取出来,分别封装起来,让它们之间可以相互替换。
接下来我们着手来改造我们的Behavior类,把我们的不同攻击方式提取出来:
package com.example.vicky.strategypattern.StrategyPattern;

/**
* Created by Vicky on 2016/10/23.
*/
//攻击的接口,为了使不同的攻击方式实现该接口,达到它们之间相互替换的效果
public interface Attack {
public void attack();
}

接着我们将魔法师的攻击行为从Behavior类中提取出来,实现Attack接口:
package com.example.vicky.strategypattern.StrategyPattern;

import android.util.Log;

/**
* Created by Vicky on 2016/10/23.
*/
//法师的行为
public class WizardBehvior implements Attack{
@Override
public void attack() {
//实现用法杖施法
Log.d("YWK","用法杖施法");

}
}

弓箭手攻击行为:
package com.example.vicky.strategypattern.StrategyPattern;

import android.util.Log;

/**
* Created by Vicky on 2016/10/23.
*/
//弓箭手的行为
public class ArcherBehavior implements Attack{
@Override
public void attack() {
//实现用弓箭射击
Log.d("YWK","用弓箭射");
}
}

勇士的攻击行为:
package com.example.vicky.strategypattern.StrategyPattern;

import android.util.Log;

/**
* Created by Vicky on 2016/10/23.
*/
//勇士的行为
public class WarriorsBehavior implements Attack{
@Override
public void attack() {
//实现用剑砍
Log.d("YWK","用剑砍");
}
}

最后是我们修造后的Behavior类:
package com.example.vicky.strategypattern.StrategyPattern;

/**
* Created by Vicky on 2016/10/23.
*/
//封装不同武器攻击行为
public class Behavior {
public Behavior(Attack attackBehavoir){
attackBehavoir.attack();
}
}

现在当我们要调用攻击方式时,只需要像下面这样写:
Behavior behavior=new Behavior(new ArcherBehavior());

是不是使用了策略模式,使我们的代码摆脱了大量的if判断语句和恼人的type来指定其中的某一算法来的清晰了很多。
而当我们现在又添加了新的职业海盗的时候,我们只需要海盗的攻击方式,让其实现Attack的接口。在Behavior实例化的时候传入海盗的攻击方式即可。

策略模式核心是定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。主要解决了在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。