欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式之策略模式

程序员文章站 2022-06-13 12:51:57
...

读书笔记:参考 Head First 设计模式,大话设计模式


设计模式要点

  • 知道OO基础,并不足以设计出良好的OO系统
  • 良好的OO设计必须具备可以复用,可扩充,可维护三个特征
  • 模式可以让我们建造出具有良好OO设计质量的系统
  • 设计模式被认为是经验验证的OO设计经验
  • 模式不是代码,而是真实设计问题的通用解决方案
  • 模式不是被发明而是被发现
  • 大多数的模式和原则,都着眼于软件变化的主题
  • 大多数模式都允许系统局部改变独立于其他部分
  • 我们常把系统中会变化的部分抽出来封装
  • 模式让开发人员之间有共享的语言,最大化沟通的价值

设计原则

  • 封装变化

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起

  • 针对接口编程,而不是针对实现编程

针对接口编程关键就在于多态,变量的声明类型应该是抽象类或一个接口,具体实现此超类型所产生的对象指定给这个变量,意味着声明类时不用理会以后执行时真正的对象类型

  • 多用组合,少用继承

策略模式定义

定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

策略模式结构图

设计模式之策略模式

代码样例

需求:一个计算商品数量和单价的小程序,后续逐渐增加需求,8折,满300返100等活动

  • 普通实现
public class SimpleCashClient {

    public static void main(String[] args) {
        System.out.println(cash(300, CashType.NORMAL, 1));
        System.out.println(cash(300, CashType.REBATE, 1));
        System.out.println(cash(300, CashType.RETURN, 1));
    }

    public static String cash(int money, CashType type, int num) {
        String result = "单价:" + money + " 数量:" + num + " 优惠:" + type.typeName();
        int total = money * num;
        switch (type) {
        case REBATE:
            BigDecimal bMoney = new BigDecimal(money);
            BigDecimal bRebate = new BigDecimal(0.8);
            total = bMoney.multiply(bRebate).intValue() * num;
            break;
        case RETURN:
            if (money >= 300) {
                total = money - ((money / 300) * 100);
            }
            break;
        default:
            break;
        }
        return result + "\n 合计:" + total;
    }
}

执行结果:

单价:300 数量:1 优惠:无
 合计:300
单价:300 数量:1 优惠:8折
 合计:240
单价:300 数量:1 优惠:满300减100
 合计:200
  • 使用策略模式实现
public class CashClient {

    public static void main(String[] args) {
        System.out.println(cash(300, CashType.NORMAL, 1));
        System.out.println(cash(300, CashType.REBATE, 1));
        System.out.println(cash(300, CashType.RETURN, 1));
    }

    public static String cash(int money, CashType type, int num) {
        String result = "单价:" + money + " 数量:" + num + " 优惠:" + type.typeName();
        int total = new CashContext(type).getResult(money) * num;
        return result + "\n 合计:" + total;
    }

}

执行结果同上

UML图
设计模式之策略模式

context

public class CashContext {

    public static enum CashType {
        REBATE, RETURN, NORMAL;
        public String typeName() {
            if (this.name().equals(REBATE.name())) {
                return "8折";
            } else if (this.name().equals(RETURN.name())) {
                return "满300减100";
            } else {
                return "无";
            }
        }
    }

    // 针对接口
    private ICash cash = new CashNormal();;

    CashContext(CashType type) {
        switch (type) {
        case REBATE:
            cash = new CashRebate(0.8);
            break;
        case RETURN:
            cash = new CashReturn(300, 100);
            break;
        default:
            cash = new CashNormal();
            break;
        }
    }

    public int getResult(int money) {
        // 多态
        return cash.acceptCash(money);
    }
}

strategy

public interface ICash {
    int acceptCash(int money);
}
public class CashNormal implements ICash {

    @Override
    public int acceptCash(int money) {
        return money;
    }
}

public class CashRebate implements ICash {
    // 默认不打折
    private double rebate = 1;

    public CashRebate(double rebate) {
        this.rebate = rebate;
    }

    @Override
    public int acceptCash(int money) {
        BigDecimal bMoney = new BigDecimal(money);
        BigDecimal bRebate = new BigDecimal(rebate);
        return bMoney.multiply(bRebate).intValue();
    }
}

public class CashReturn implements ICash {
    // 返利条件
    private int returnCondition = 0;
    // 返利金额
    private int returnMoney = 0;

    public CashReturn(int returnCondition, int returnMoney) {
        this.returnCondition = returnCondition;
        this.returnMoney = returnMoney;
    }

    @Override
    public int acceptCash(int money) {
        if (money >= returnCondition) {
            return money - ((money / returnCondition) * returnMoney);
        }
        return money;
    }
}

策略模式解析

  • 策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合

  • 策略模式的Strategy类层次,为Context定义了一系列的可供重用的算法或行为,继承有助于析取这些算法中的公共功能

  • 策略模式封装了变化

  • 当不同行为堆砌在一个类中时,难免使用条件语句来选择合适的行为,将这些行为封装在独立的Strategy类中,可以在使用这些行为的类中消除条件语句.

  • 策略模式不光可以封装算法可以封装几乎任何类型的规则,只要需要不同的时间应用不同的业务规则,就可以考虑策略模式

  • 可以用反射进一步代替选择具体实现的逻辑