行为型模式:类和对象如何交互,划分责任和算法,即对象之间通信。
概念
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
结构
策略模式的结构如下图所示,
image.png这个模式涉及到三个角色:
-
上下文环境(Context)角色:持有一个Strategy的引用。
-
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
-
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
实例
上面的都是概念,下面以工作中用到的实例讲解可能更加清楚。
电商中,对商品的价格计算是比较麻烦的,不同等级的会员,折扣、优惠券、运费券、积分(不同等级的会员积分兑换的金额可能不一样),当用户下单或者商品详情页展示商品价格时,就需要根据不同的等级来计算商品价格。最简单的情况是直接使用if-else,但是如果算法比较多(算法是会随着公司业务发展阶段不断调整的),就会使得代码越来越很臃肿,后期维护越来越麻烦。
这种情形,就适合使用策略模式,我们根据不同的情况,将不同的算法封装成不同的策略,将策略与它的使用对象分离开来。
首先创建抽象策略角色和具体策略角色
/**
* 抽象策略
**/
public interface PriceStrategy {
BigDecimal getPrice(BigDecimal price);
}
/**
* 会员,六折
**/
class Member implements PriceStrategy {
@Override
public BigDecimal getPrice(BigDecimal price) {
return price.multiply(new BigDecimal(0.6 + ""));
}
}
/**
* 普通客户 原价
**/
class Ordinary implements PriceStrategy {
@Override
public BigDecimal getPrice(BigDecimal price) {
return price;
}
}
/**
* 超级会员,4折
**/
class SuperMember implements PriceStrategy {
@Override
public BigDecimal getPrice(BigDecimal price) {
return price.multiply(new BigDecimal(0.4+""));
}
}
然后创建上下文环境角色,并且其持有一个抽象策略对象
/**
* 上下文
**/
class PriceContext {
//持有一个具体策略的对象
private PriceStrategy priceStrategy ;
/**
* 构造函数,传入一个具体策略对象
* @param strategy 具体策略对象
*/
public Context(PriceStrategy priceStrategy){
this.priceStrategy = strategy;
}
/**
* 策略方法
*/
public void getPrice(BigDecimal price){
strategy.getPrice(price);
}
}
public class Test {
public static void main(String[] args) throws Exception {
//选择并创建需要使用的策略对象(这里可以用工厂模式来创建所需要的策略对象)
PriceStrategy strategy = new SuperMember();
// 创建上下文环境
PriceContext priceContext = new PriceContext(strategy);
// 计算价格
BigDecimal price = priceContext.getPrice(300);
System.out.println("商品的最终价格为:" + price );
}
}
从上面的例子可以看出,在计算商品价格的业务代码中,并不会引入太多的if-else条件判断,且对于不同的策略/算法可以随时切换,这对于业务代码的解耦是相当有帮助的。在实际业务中,我们可以把创建策略对象的过程使用工厂模式根据用户id来创建。
网友评论