您的位置:首页 > 编程语言 > Java开发

开发者模式之—-策略者模式

2017-01-06 09:51 148 查看

开发者模式之—-策略者模式

—序言:本文为《Androdi源码及开发模式》的学习笔记。更详细内容请购买查看该正版书籍。

在开发中,当一个任务有多个解决方案时,最简单的方式就是使用 if-else或者 switch -case来实现。但是如果因为if-else这种方法不会遵守开闭原则,所以耦合性很高,当要继续添加功能时,就要修改原来的代码。

而应对这种情况最好的方案就是使用策略者模式,把各种方案分离开来,让程序客户端根据具体的需求来动态选择不同的策略。

以下为策略者的UML图:



下面,我们来一出行时乘坐的交通工具票价计算来分析策略者模式的应用。

以下是最简单的用swtch-case实现的:

/**
* author: ZK.
* date:   On 2016/12/18
*  用switch-case实现的计算器
*/

public class NormalCalculator {

public enum TrafficType {
BUS, SUBWAY
}

private final String NORMAL_TAG = "----normal_tag";

public void calcutePrice(TrafficType trafficType, int km) {
switch (trafficType) {
case BUS:
Log.d(NORMAL_TAG, km + "公里,公交车价格为:" + busPrice(km) + "元");
break;
case SUBWAY:
Log.d(NORMAL_TAG, km + "公里,地铁价格为:" + subwayBus(km) + "元");
}
}

private int busPrice(int km) {
if (km < 5) {
return 3;
} else if (km > 5 && km < 10) {
return 5;
} else {
return 8;
}
}

private int subwayPrice(int km) {
if (km < 6) {
return 3;
} else if (km > 6 && km < 12) {
return 5;
} else {
return 7;
}
}


调用时,只需实例化NormalCalculator ,调用calculate方法就可以了。

NormalCalculator calculator = new NormalCalculator();
calculator.calcutePrice(NormalCalculator.TrafficType.TAXI,10);


代码看起来非常简单,直接调用calcute方法,传入交通类型和距离便可以得出价格了。但是现在我又有个需求了,现在我要添加计算出租车的价格这个需求,这时有人会说,这很简单嘛,不就再写一个taxi(int km)的方法,然后在calcute的switch里面添加相应的类型计算不就行了么。是的,确实看起来很简单,但我需求不停变化时,就需要不停地在原来的代码上修改,这样耦合性就非常高,很容易变得臃肿而且出错。

public class NormalCalculator {

public enum TrafficType {
BUS, SUBWAY, TAXI
}
private final String NORMAL_TAG = "----normal_tag";

public void calcutePrice(TrafficType trafficType, int km) {
switch (trafficType) {
case BUS:
Log.d(NORMAL_TAG, km + "公里,公交车价格为:" + busPrice(km) + "元");
break;
case SUBWAY:
Log.d(NORMAL_TAG, km + "公里,地铁价格为:" + subwayBus(km) + "元");
break;
case TAXI:
Log.d(NORMAL_TAG, km + "公里,的士价格为:" + taxiPrice(km) + "元");
}
}

private int busPrice(int km) {
if (km < 5) {
return 3;
} else if (km > 5 && km < 10) {
return 5;
} else {
return 8;
}
}

private int subwayBus(int km) {
if (km < 6) {
return 3;
} else if (km > 6 && km < 12) {
return 5;
} else {
return 7;
}
}
private int taxiPrice(int km) {
return km * 2;
}
}


好了,下面,大招来了。下面,我们来用策略者模式去实现这方案。

首先写一个计算器的接口,提供一个计算的方法:

public interface StrategyCalculator {
int calculate(int km);
}


好了。你要交通工具的计算方案?你自己去另外创建,你只要实现我这个接口,里面怎样的计算价格你自己实现就好。

公交车,是吗?

public class BusCalculator implements StrategyCalculator {
@Override
public int calculate(int km) {
if (km < 5) {
return 3;
} else if (km > 5 && km < 10) {
return 5;
} else {
return 8;
}
}
}


地铁又怎样:


public class SubwayCalculator implements StrategyCalculator {
@Override
public int calculate(int km) {
if (km < 6) {
return 3;
} else if (km > 6 && km < 12) {
return 5;
} else {
return 7;
}
}
}


出租车的需求来了,怕啥?妥妥的new class implement***,稳!

public class TaxiCalculator implements StrategyCalculator {
@Override
public int calculate(int km) {
return km * 2;
}
}


好了,你要计算交通方式的价格?

StrategyCalculator calculator = new BusCalculator();
calculator.calculate(10);


注意,实例化的是你需要的计算器(BusCalculator),但调用者仍然是接口计算器(StrategyCalculator)。由父接口去调用方法,但具体实现还是由BusCalculator去处理。这样BusCalculator里面的实现就没必要暴露给外面知道,使用者只需调用我这接口的方法就可以了,具体内部自己会处理。点击calculate方法查看内部实现时,看到的只是接口的方法而已。如下:





从以上可以看到使用策略者模式,各个交通工具的计算器之间都是独立的,相互之间没有关联。当我需要增加一个交通工具是,你也是只需创建一个类实现这接口,重写方法就行了。这样在业务逻辑显得更为直观和简单的儿童诗,扩展也更为方便。

在Android源码中的策略者模式实现:

Android的动画过程中,切换的频率是不一定的,有可能是匀速,有可能是加速。这时动画就需要通过一个时间插值器实现这种效果。这时需求来了,我要匀速,我要加速的。我要时快是慢的,这时和上面的交通工具计算器是不是很类似。



示例代码链接:

设计模式Demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息