当Android遇上设计模式之策略(Strategy)模式

转载请声明出处: http://blog.csdn.net/AndrExpert/article/details/79603560

 记得16年在开发”路痴宝“APP时,里面有这么一个业务逻辑:当用户输入起点地址和终点地址后,路痴宝可提供驾车、公交、步行、骑行等多种出行方式,当用户选中了哪种出行方式后,就会根据约定好的条件通过if--else调用相应的业务逻辑代码实现路线查询功能。从功能的设计上来说,使用if--else进行逻辑判断也没有什么不妥,但是从架构设计来说,这种方式其实是非常不优雅的,因为如果需要添加更多的出行方式,就必须去修改原有的代码,这会直接导致代码块臃肿、扩展性差以及后期维护困难,更违反了设计模式中的”开放-封闭”原则。那么应该如何去改进它呢?答案是:策略模式!

1.策略模式简介

1. 1 定义

 策略模式是一种常见的行为型设计模式,其定义可表述为:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以互相替换。简单来说,就是对所有算法进行抽象提出,以提供一个统一的接口,不同的算法通过继承该接口实现,然后客户端通过注入不同的实现类对象来实现算法的动态替换,最终让算法独立于使用它的客户端而独立变化。常见的使用场景有:
 (1)  针对同一类型问题有多种处理方式,仅仅是具体行为有差别时;
 (2)  出现同一抽象类有多个子类,且需要使用if-else或者switch-case来选择具体子类时;

1.2 UML类图

image

角色分析:

 (1) Context:用来操作算法/策略的上下文环境,即客户端;
 (2) Stragety:算法/策略抽象接口;
 (3) ConcreteStragetyAConcreteStragetyB:具体算法实现类;

2.Android项目实战

 为了让大家对上述提及的例子有个直观了解,我们打开”路痴宝“APP,进入路线查询界面,输入起始地址和终点地址,开始查询就会看到如下图所示:
这里写图片描述
 首先,贴下以前实现的业务逻辑代码,但为了便于把握策略模式,我把相关的代码以打印一个Toast代替,代码如下:

  • RouteSearchActivity:客户端,调用路线查询业务逻辑
class RouteSearchActivity extends Activity{
    // 路线查询业务逻辑类  
    private RouteWaySearch mSearch;

       @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        onCreateView();
        mSearch = new RouteWaySearch(this);
    }

    // 点击事件
    // 根据不同类型查询路线
    public void onSearchClick(View v) {
        startSearchRoute(type,cityBean);
    }

    private void startSearchRoute(int routeType,CityParamsBean cityBean) {
        String startCity = cityBean.getStartCity();
        String startPlace = cityBean.getStartPlaceName();
        String endCity = cityBean.getEndCity();
        String endPlace = cityBean.getEndPlaceName();
        switch (routeType) {
            case Constants.WAY_PUBLIC_BUS:
                routeLogic.searchTransitRoute(startCity,startPlace,endCity,endPlace);
                Log.d("debug","开始搜索-->公交路线");
                break;
            case Constants.WAY_STEP:
                routeLogic.searchWalkRoute(startCity,startPlace,endCity,endPlace);
                Log.d("debug","开始搜索-->步行路线");
                break;
            case Constants.WAY_CAR:
                routeLogic.searchDriveRoute(startCity,startPlace,endCity,endPlace);
                Log.d("debug","开始搜索-->驾车路线");
                break;
            case Constants.WAY_BIKE:
                routeLogic.searchBikeRoute(startCity,startPlace,endCity,endPlace);
                Log.d("debug","开始搜索-->骑行路线");
                break;
            default:
                break;
        }
    }
}
  • RouteWaySearch:具体路线查询业务逻辑类
class RouteWaySearch {

    private Context mContext;

    public RouteWaySearch(Context ctx) {
        this.mContext = ctx.getApplicationContext();
    }

    public void searchTransitRoute(String startCity,
            String startPlaceName, String endCity, String endPlaceName) {
        Toast.make(mContext,"查询公交车路线",Toast.LENGTH_SHORT).show();
    }

       public void searchWalkRoute(String startCity,
            String startPlaceName, String endCity, String endPlaceName) {
        Toast.make(mContext,"查询步行路线",Toast.LENGTH_SHORT).show();
    }

       public void searchDriveRoute(String startCity,
            String startPlaceName, String endCity, String endPlaceName) {
        Toast.make(mContext,"查询驾车路线",Toast.LENGTH_SHORT).show();
    }

       public void searchBikeRoute(String startCity,
            String startPlaceName, String endCity, String endPlaceName) {
        Toast.make(mContext,"查询骑行路线",Toast.LENGTH_SHORT).show();
    }

}

 从上面的代码可知,如果需要添加新的出行方式,就必须在RouteWaySearch类中添加searchXXXRoute方法,客户端RouteSearchActivity中也要添加相应的case判断。如果此时需要添加数十种出行方式,其维护是非常糟糕的,且代码会变得越来越臃肿。接下来,我们使用策略模式来改进它。先看看它的UML类图:

image

  • ISearchWay:出行方式抽象接口,策略模型中的Stragety接口
/** 搜索方式抽象接口
 * Created by jianddongguo on 2018/3/18.
 */

public interface ISearchStragety {
    void searchRouteWay(String startPlaceName, String endPlaceName);
}
  • BikeSearchWay:骑行出行,策略模型中Stragety的子类
/**出行策略具体实现类,骑行出行
 * Created by jianddongguo on 2018/3/18.
 */

public class BikeSearchStragety implements ISearchStragety {

    @Override
    public void searchRouteWay(String startPlaceName, String endPlaceName) {
        Log.i("tag","搜索骑行出行结果");    
    }
}
  • WalkSearchWay:步行出行,策略模型中Stragety的子类
/**出行策略具体实现类,步行出行
 * Created by jianddongguo on 2018/3/18.
 */

public class WalkSearchStragety implements ISearchStragety {
    @Override
    public void searchRouteWay(String startPlaceName, String endPlaceName) {
        Log.i("tag","搜索步行出行结果");
    }
}
  • ClientActivity:客户端,策略模型中Context上下文环境
public class ClientActivity extends AppCompatActivity {
    private ISearchStragety mSearchStragety;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onBikeSearchClick(View view) {
        setStragety(new BikeSearchStragety());
        mSearchStragety.searchRouteWay("大学城南","南沙天后宫");
    }

    public void onWalkSearchClick(View view) {
        setStragety(new WalkSearchStragety());
        mSearchStragety.searchRouteWay("大学城南","南沙天后宫");
    }

    // 设置出行策略
    private void setStragety(ISearchStragety mSearchStragety) {
        this.mSearchStragety = mSearchStragety;
    }

    // 执行搜索策略
    private void searchRouteWay(String startPlace,String endPlace) {
        mSearchStragety.searchRouteWay(startPlace,endPlace);
    }
}

 至此为止,对路痴宝路线查询模块代码重构基本完成。可以看出,通过策略模式来实现出行策略的选择灵活度大大提供,各出行策略基本保持独立,且易于添加或删减策略,降低了代码维护成本。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页