(what)什么是策略模式【定义】?
对算法(策略)进行封装,让调用方能很方便的切换不同的算法(策略)。
(how)怎样使用策略模式【原理】?
直接上代码:
package strategy.example2.strategy;
import java.math.BigDecimal;
/**
*
* @Title CashStrategy.java
*
* @Description: TODO 收费策略
*
* @author heps
*
*/
public interface CashStrategy {
/**
* 收费方法
* @param total 商品金额
* @return 优惠后应收金额
*/
BigDecimal cash(BigDecimal total);
}
package strategy.example2.strategy;
import java.math.BigDecimal;
/**
*
* @Title NormalCash.java
*
* @Description: TODO 普通收费策略
*
* @author heps
*
*/
public class NormalCash implements CashStrategy{
@Override
public BigDecimal cash(BigDecimal total) {
if(null == total){
throw new IllegalArgumentException("total can not be null!");
}
if(total.compareTo(BigDecimal.ZERO) <=0 ){
throw new IllegalArgumentException("total can not be negative!");
}
return total;
}
}
package strategy.example2.strategy;
import java.math.BigDecimal;
/**
*
* @Title SaleAmountCash.java
*
* @Description: TODO 满多少减多少收费策略
*
* @author heps
*
*/
public class SaleAmountCash implements CashStrategy{
/**打折金额,减多少**/
private BigDecimal discountAmount = new BigDecimal("100");
/**条件金额,满多少**/
private BigDecimal conditionAmount = new BigDecimal("1000");
public BigDecimal getDiscountAmount() {
return discountAmount;
}
public void setDiscountAmount(BigDecimal discountAmount) {
if(null == discountAmount){
throw new IllegalArgumentException("discountAmount can not be null!");
}
if(discountAmount.compareTo(BigDecimal.ZERO) <=0 ){
throw new IllegalArgumentException("discountAmount can not be negative!");
}
this.discountAmount = discountAmount;
}
public BigDecimal getConditionAmount() {
return conditionAmount;
}
public void setConditionAmount(BigDecimal conditionAmount) {
if(null == conditionAmount){
throw new IllegalArgumentException("conditionAmount can not be null!");
}
if(conditionAmount.compareTo(BigDecimal.ZERO) <=0 ){
throw new IllegalArgumentException("conditionAmount can not be negative!");
}
this.conditionAmount = conditionAmount;
}
@Override
public BigDecimal cash(BigDecimal total) {
if(null == total){
throw new IllegalArgumentException("total can not be null!");
}
if(total.compareTo(BigDecimal.ZERO) <=0 ){
throw new IllegalArgumentException("total can not be negative!");
}
BigDecimal cash = total;
if(total.compareTo(conditionAmount) >= 0){
cash = cash.subtract(discountAmount);
}
return cash;
}
}
package strategy.example2.strategy;
import java.math.BigDecimal;
/**
*
* @Title SalePercentCash.java
*
* @Description: TODO 折扣收费策略
*
* @author heps
*
*/
public class SalePercentCash implements CashStrategy{
/**打几折小数**/
private double percent = 0.95;
public double getPercent() {
return percent;
}
public void setPercent(double percent) {
if(0 >= percent || 1 <= percent){
throw new IllegalArgumentException("percent must between 0 and 1!");
}
this.percent = percent;
}
@Override
public BigDecimal cash(BigDecimal total) {
if(null == total){
throw new IllegalArgumentException("total can not be null!");
}
if(total.compareTo(BigDecimal.ZERO) <=0 ){
throw new IllegalArgumentException("total can not be negative!");
}
return total.multiply(new BigDecimal(percent+""));
}
}
package strategy.example2.context;
import java.math.BigDecimal;
import strategy.example2.strategy.CashStrategy;
/**
*
* @Title Cashier.java
*
* @Description: TODO 收银员
*
* @author heps
*
*/
public class Cashier {
/**收费策略**/
private CashStrategy cashStrategy;
public CashStrategy getCashStrategy() {
return cashStrategy;
}
public void setCashStrategy(CashStrategy cashStrategy) {
this.cashStrategy = cashStrategy;
}
/**
* 收费方法
* @param total 商品总价
* @return 优惠后应收金额
*/
public BigDecimal cash(BigDecimal total){
return cashStrategy.cash(total);
}
}
package strategy.example2;
import java.math.BigDecimal;
import strategy.example2.context.Cashier;
import strategy.example2.strategy.SaleAmountCash;
import strategy.example2.strategy.SalePercentCash;
public class Test {
public static void main(String[] args) {
BigDecimal total = new BigDecimal("1000");
BigDecimal cash = null;
Cashier cashier = new Cashier();
cashier.setCashStrategy(new SaleAmountCash());
cash = cashier.cash(total);
System.out.println(new StringBuffer("total:").append(total).append(",need to pay:").append(cash));
cashier.setCashStrategy(new SalePercentCash());
cash = cashier.cash(total);
System.out.println(new StringBuffer("total:").append(total).append(",need to pay:").append(cash));
}
}
【总结】
(when)什么时候使用【场景】?
当需求中需要给同一对象(客户/产品)制定一系列的规则(算法/策略)时,可以将这些同一纬度的规则单独封装起来,并聚合到调用者(上下文)内部来进行调用。
(why)为什么要用策略模式【设计原则】?
1. Identify the aspects of your application that vary and separate them from what stays the same.
* (找到系统中变化的部分,将变化的部分同其它稳定的部分隔开。变化的部分隔离成接口,聚合到需要的程序里)【扩展性好】
2. Program to an interface, not an implementation.
* (面向接口编程,而不要面向实现编程。通过聚合、实现接口等方式)【灵活性好】