我们写代码的时候,有时会写很多if...else if....else...的条件语句,或者switch...case...case... 。。。 这会使我们的代码非常臃肿,策略模式的目的就是避免了各种条件判断的臃肿代码,使代码更加可读,而且方便后期维护。
一、定义
策略模式定义了一系列算法或逻辑,并将每一个算法或逻辑封装起来,而且使它们可以相互替换,策略模式让算法或逻辑独立于使用者。使用者只需设置相应的策略去实现相应目的,而无需知道策略中的具体实现方法。
UML:
Context:用来操作策略的上下文环境
Stragety:策略的抽象定义
ConcreteStrageryA/B:具体的策略实现
二、使用场景
1、针对同一类型问题的多重处理方式,仅仅是具体行为有偏差。
2、需要安全的封装同一种类型操作。
3、出现同一抽象类有多个子类,而又需要使用if...else...或者switch..case...来选择具体子类。
同一问题有多种解决方案
三、简单实现
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
public static final int AM = 0x010;//上午
public static final int PM = 0x011;//下午
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test("星期二", PM);
}
private void test(String day, int time) {
String doSomething = "";
switch (day) {
case "星期一":
if (time == AM)
doSomething = "敲代码";
else if (time == PM)
doSomething = "开会";
break;
case "星期二":
if (time == AM)
doSomething = "架构";
else if (time == PM)
doSomething = "测试";
break;
case "星期三":
if (time == AM)
doSomething = "写文档";
else if (time == PM)
doSomething = "偷懒";
break;
default:
doSomething = "闲待着";
break;
}
Log.d(TAG, "今天我要做的事情是" + doSomething);
}
}
我们可以看到,一直不停的case确实可以满足我们的需求,但是后期维护相当麻烦,比如添加周六,或者周日,要一直不停的case...很不好写,而且代码臃肿不堪,我们要降低代码的耦合性,什么是耦合性?耦合性是各模块间相互联系程度的一种度量,也就是说,我们要尽可能的独立每一个类,使其可以单独调用,而尽可能少的依赖其他类,下面介绍一下策略模式,大大降低耦合性,先写一个接口Day:
public interface Day {
String doSomething(int time);
}
以星期一和星期二为例:
public class Monday implements Day {
@Override
public String doSomething(int time) {
if (time == MainActivity.AM)
return "敲代码";
else
return "开会";
}
}
public class Tuesday implements Day {
@Override
public String doSomething(int time) {
if (time == MainActivity.AM)
return "架构";
else
return "测试";
}
}
我们用的时候 只需这样:
Day day = new Tuesday();
String doSomething = day.doSomething(PM);
Log.d(TAG, "今天我要做的事情是" + doSomething);
如果要添加新的种类 比如周日,不用再去写case...if else...只需要写一个Sunday然后实现Day接口就可以了!
public class Sunday implements Day {
@Override
public String doSomething(int time) {
if (time == MainActivity.AM)
return "吃饭、睡觉";
else
return "打豆豆";
}
}
四、例子
写一个简单算法计算出行的价格
普通实现:
public class PriceCalculator {
private static final int BUS = 0x010;
private static final int SUBWAY = 0x011;
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator();
System.out.print("坐16公里公交的价格为:" + calculator.make(16, BUS));
System.out.print("坐16公里地铁的价格为:" + calculator.make(16, SUBWAY));
}
private int make(int km, int type) {
if (type == BUS) {
return bugMake(km);
} else if (type == SUBWAY) {
return subwayMake(km);
} else {
return 0;
}
}
private int bugMake(int km) {
if (km > 10) {
return 3;
} else {
return 2;
}
}
private int subwayMake(int km) {
if (km < 6) {
return 3;
} else if (km > 6 && km < 12) {
return 4;
} else if (km > 12 && km < 22) {
return 5;
} else if (km > 22 && km < 32) {
return 6;
} else {
return 7;
}
}
}
上面的代码虽然计算上是没有问题,但是很明显违背了单一职责原则,而且当我们增加一种新的出行方式比如TAXI,我们就需要在PriceCalculator中增加一个计算方法,最后使得该类中的代码越来越臃肿,耦合性越来越大。
使用策略模式实现,使得每一种出行方式都有一个独立的类去计算:
public interface PriceCalculator {
int make(int km);
}
public class BusPrice implements PriceCalculator {
@Override
public int make(int km) {
if (km > 10) {
return 3;
} else {
return 2;
}
}
}
public class SubwayPrice implements PriceCalculator {
@Override
public int make(int km) {
if (km < 6) {
return 3;
} else if (km > 6 && km < 12) {
return 4;
} else if (km > 12 && km < 22) {
return 5;
} else if (km > 22 && km < 32) {
return 6;
} else {
return 7;
}
}
}
public class TaxiPrice implements PriceCalculator {
@Override
public int make(int km) {
if (km < 6) {
return 13;
} else {
int extarKm = km - 6;
int extarMoney = extarKm * 3;
return 13 + extarMoney;
}
}
}
在使用的时候,我们只需要这样做:
public class TrafficPriceCalculator {
private PriceCalculator calculator;
public static void main(String[] args) {
TrafficPriceCalculator calculator = new TrafficPriceCalculator();
calculator.setCalculator(new BusPrice());
System.out.print("坐16公里公交的价格为:" + calculator.make(16));
calculator.setCalculator(new SubwayPrice());
System.out.print("坐16公里地铁的价格为:" + calculator.make(16));
calculator.setCalculator(new TaxiPrice());
System.out.print("坐16公里出租车的价格为:" + calculator.make(16));
}
public void setCalculator(PriceCalculator calculator) {
this.calculator = calculator;
}
public int make(int km) {
return calculator.make(km);
}
}