美文网首页Android开发
Android中的设计模式之策略模式

Android中的设计模式之策略模式

作者: WangGavin | 来源:发表于2018-04-03 22:09 被阅读6次

    参考

    • 《设计模式:可复用面向对象软件的基础 》5.9 Strategy--对象行为型模式
    • 《设计模式解析》(第二版)第九章 Strategy模式
    • 《Android源码设计模式解析与实战》第七章策略模式

    处理新需求的一种途径

    • 灾难往往是由短期未甄选最优的决策,长期积累而引起的

    • 在软件开发中也是如此,只关心眼前的事情,而忽视长期问题
      原因:

    • 我们确实无法预测新需求将如何变化

    • 如果要把软件编写得能够方便地添加新功能,在设计阶段就永远止步不前了

    • 客户或老板正死死盯着我们的进度,要求立即实现,我们没有时间多想。

    • 我们以后会考虑这个问题

    • 似乎就是两种选择:

      • 过度分析或过度设计
      • 一上来就扎进细节中,编写代码,根本不考虑长期问题。

    考虑变化的设计

    • 针对接口进行编程,而不要针对实现编程。
    • 优先使用对象组合,而不是类继承
    • 考虑设计中什么应该是可变的,关注对变化的概念进行封装

    例子1:国际电子商务系统

    这个系统的总架构中有一个控制器对象,用于处理销售请求。他能够确认何时有人在请求销售订单,并将请求转发给SalesOrder对象进行订单处理。

    总架构中的SalesOrder

    SalesOrder对象的功能包括:

    • 允许客户通过GUI填写订单
    • 处理税额的计算
    • 处理订单,打印销售数据

    当然这些功能可以借助其他对象去实现,他的作用应该是充当一个存在销售订单信息的容器。

    处理新的需求

    比如必须处理美国之外的顾客的订单税额。
    那么我们至少需要添加新的税额计算规则

    那么该怎样添呢?

    • 复制和粘贴
      一份代码,两个版本,维护很麻烦
    • 使用switch或者if语句,用一个变量指定各种情况
      如果有很多个国家呢?以后添加国家还要慢慢检查分支,看漏掉那个国家没有。条件复杂后,分支的流向也开始模糊了,反而难以阅读和理解。
    • 使用函数指针或者委托
      函数指针和委托无法维持每个对象的状态,功能受限。
    • 继承
      如果错误使用,继承会使设计非常脆弱和僵化。

    比如:


    继承方案

    这种方案的困难之处在于,它这次能够凑效,但是无法次次凑效,比如,如果要处理德国订单,或者应对其他方面发生变化(如日期格式,语言和运费规则),我们构建的继承层次将无法轻松应对

    使用策略模式方法

    第一步 发现变化并封装之

    在本例中,已经确定缴税规则是变化的,“将它封装”就应该创建一个抽象类定义如何在概念上完成税额计算,然后根据每种变化派生具体类。

    封装变化

    第二步 组合优先

    应该使用组合代替继承,用组合包含变化,也就是说,只有一个SalesOrder类,让它包含处理变化的CalcTax类

    组合代替继承

    直接继承方和策略模式方案比较

    一个是自己直接派生处理变化,另一个是包含引用指向变化,当然是后一种好,因为一些税额业务规则能更好的独立于使用自己的SalesOrder

    《设计模式》中的Strategy 模式

    意图

    可以根据上下文,使用不同的业务规则或算法

    解释

    定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,Strategy模式使算法可独立于使用它的客户而变化。

    原则

    • 对象都具有指责
    • 这些指责不同的具体实现是通过多态的使用完成的
    • 概念上相同的算法具有多个不同的实现,需要进行管理

    角色

    • Context 用来操作策略的上下文环境,比如上面说的Calculator类
    • Stragety 策略的对象
    • ConcreteStragetyA,ConcreteStragetyB 具体的策略实现


      策略模式UML类图

    示例代码

    public class PriceCalculator {
    private Stragety stragety;
        public void setStragety(Stragety stragety){
            this.stragety=stragety;
        }
        
    public void calculatePrice(int km) {
        int price=0;
        if (stragety!=null) {
            price=stragety.calculatePrice(km);
        }
        System.out.println(String.valueOf(price));
    }
    }
    public class Bus implements Stragety{
        @Override
        public int calculatePrice(int km) {
            return 3*km;
        }
        
    }
    public class Subway implements Stragety{
        
        @Override
        public int calculatePrice(int km) {
            return 5*km;
        }
        
    }
    public class Taxi implements Stragety{
        
        @Override
        public int calculatePrice(int km) {
            return 2*km;
        }
        
    }
        public static void main(String[] args) {
            PriceCalculator laowang=new PriceCalculator();
            laowang.setStragety(new Bus());
            laowang.calculatePrice(3);
            laowang.setStragety(new Subway());
            laowang.calculatePrice(3);
            laowang.setStragety(new Taxi());
            laowang.calculatePrice(3);
        }
    

    效果

    使用if-else暴露的问题是代码臃肿,逻辑复杂,难以升级和维护,没有结构可言;策略模式是通过建立抽象,将不同的策略构建成一个具体的策略实现,通过不同的策略实现算法替换。在简化逻辑,结构的同时,增强了系统的可读性,稳定性,可扩展性。

    应用例子2 Android动画中的时间插值器

    待研究

    相关文章

      网友评论

        本文标题:Android中的设计模式之策略模式

        本文链接:https://www.haomeiwen.com/subject/sifhhftx.html