本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Android中的策略模式
策略模式的本质是分离算法,选择实现。通俗的说就是找出应用中可能需要变动的地方,把它们独立出来,并封装起来,不要和那些不需要变化的代码混在一起 ,使代码更加有弹性和扩展性。
比如商品的打折方式,买一件是9折价格 买2件85折 买3件减10元等,实现不同的购买方式不同的优惠策略。
比如我们旅行的方式你可以选择坐地铁,徒步或者坐飞机等等,实现不同的出行方式,跳转不同的页面。
一、出行的例子
平常如果不使用设计模式,我们都是这么写的,if else
public class TravelStrategy {
enum Strategy{
WALK,PLANE,SUBWAY
}
private Strategy strategy;
public TravelStrategy(Strategy strategy){
this.strategy=strategy;
}
public void travel(){
if(strategy==Strategy.WALK){
System.out.println("出行旅游的方式为:"+WALK);
}else if(strategy==Strategy.PLANE){
System.out.println("出行旅游的方式为:"+PLANE);
}else if(strategy==Strategy.SUBWAY){
System.out.println("出行旅游的方式为:"+SUBWAY);
}
}
public static void main(String[] args) {
TravelStrategy walk=new TravelStrategy(Strategy.WALK);
walk.travel();
TravelStrategy plane=new TravelStrategy(Strategy.PLANE);
plane.travel();
TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY);
subway.travel();
}
}
如果逻辑复杂,或者出行的方式变多,那么简直不堪重负,我们可以定义一个策略,实现不同的出行策略。
public interface Strategy {
void travel();
}
然后根据不同的出行方法来实现该接口
public class WalkStrategy implements Strategy{
@Override
public void travel() {
System.out.println("walk");
}
}
public class PlaneStrategy implements Strategy{
@Override
public void travel() {
System.out.println("plane");
}
}
public class SubwayStrategy implements Strategy{
@Override
public void travel() {
System.out.println("subway");
}
}
还需要一个包装策略的类,来调用策略中的接口
public class TravelContext {
privite Strategy strategy;
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void travel() {
if (strategy != null) {
strategy.travel();
}
}
}
使用:
TravelContext travelContext=new TravelContext();
travelContext.setStrategy(new PlaneStrategy());
travelContext.travel();
travelContext.setStrategy(new WalkStrategy());
travelContext.travel();
travelContext.setStrategy(new SubwayStrategy());
travelContext.travel();
优点很明显,我们添加更多的出行方式,只需要实现指定的策略就能完成不同的功能。
二、商品打折
需求是:买一件是9折价格 买2件85折 买3件减10元。
目标是我只需要告诉对象,我买了几件,原价是多少,它告诉我总价是多少钱。
设计一个打折的接口:
public interface IDisCount {
float getPrice(int originPrice);
}
public class DisCountControl {
private IDisCount iDisCount;
//打折方式
public void setDisCount(IDisCount iDisCount){
this.iDisCount = iDisCount;
}
//返回总价格
public float getFinalPrice(int originCash){
return this.iDisCount.getPrice(originCash);
}
}
单件打9折:
public class OneCountPercent implements IDisCount {
@Override
public float getPrice(int originPrice) {
return originPrice * 0.9;
}
}
买2件85折
public class TwoCountPercent implements IDisCount {
@Override
public float getPrice(int originPrice) {
return originPrice * 2 * 0.85;
}
}
买3件减10元
public class ThreeCountPercent implements IDisCount {
@Override
public float getPrice(int originPrice) {
return (originPrice * 3 ) - 10.0;
}
}
使用
DisCountControl disCountControl = new DisCountControl();
//单件
disCountControl.setDisCount(new OneCountPercent());
Log.d(TAG, "我买了一件衣服: "+disCountControl.getFinalPrice(120));
//买两件
disCountControl.setDisCount(new TwoCountPercent());
Log.d(TAG, "我买了两件衣服: "+disCountControl.getFinalPrice(120));
//买了三件
disCountControl.setDisCount(new ThreeCountPercent());
Log.d(TAG, "我买了三件衣服: "+disCountControl.getFinalPrice(120));
比如后期我们再加入买4件怎么打折 买5件怎么打折 都可以很方便的实现了。
总结
Android Api中 listView.setAdapter()就是典型的策略模式: 比如只是简单处理文字,我们可以使用 arrayAdapter,simpleAdapter,而稍微复杂一点的,则是使用 baseadapter,但最终我们调用的都是 setAdapter。
优点:
- 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
- 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
- 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点:
- 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
其实策略模式也是很简单的,都是固定的模板,使用一个借口定义策略,然后定义个一个管理类管理策略,然后定义不同的策略实现类就行了。
最后也是感谢看到最后,如果觉得不错还请点赞支持!