大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正
如果你从本文 get 到有用的干货知识,请帮忙点个赞呗,据说点赞的都拿到了offer
策略模式
简介:
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
当然以上是比较官方的解释,不理解也没什么,因为接下来我会通过生动的案例来解释的
引申案例
我去买空调,店内卖空调搞活动
我作为客户去买空调,我提供给收银员我的身份,而收银员根据我的身份进行计算我买的空调实际该支付的价格
案例分析
案例中出现的对象:收银员,我(客户) 关系:收营员有一个专门用于根据客户身份计算实际支付金额的算法,不同的身份算法不一样
案例代码
收银员(PriceHandler,名字取的有点对不上号,哈哈,大家知道什么意思就好,不要在意这些细节)
这个价格处理类的做法是让客户给出int身份()1表示新客户,2表示一年老客户,3表示三年老客户),然后通过switch用不同的算法计算对应身份的客户具体支付的价格,为了体现可读性,switch中的case后面用的不是1,2,3,而是静态常量
package strategy;
public class Identity {
public static final int NEW_CUSTOMER = 1;
public static final int OLD_CUSTOMER_ONE = 2;
public static final int OLD_CUSTOMER_THREE = 3;
}
package strategy;
@SuppressWarnings("all")
public class PriceHandler {
public double dealPrice(double originalPrice, int identity){
System.out.println("价格处理中......");
double res = originalPrice;
switch (identity){
case Identity.NEW_CUSTOMER:
res = this.calculateForNewCustomer(originalPrice);
break;
case Identity.OLD_CUSTOMER_ONE:
res = this.calculateForOneOldCustomer(originalPrice);
break;
case Identity.OLD_CUSTOMER_THREE:
res = this.calculateForThreeOldCustomer(originalPrice);
break;
default:
break;
}
System.out.println("价格生成中......");
return res;
}
private double calculateForNewCustomer(double originalPrice){
System.out.println("当前客户属于新客户,立减500");
return originalPrice - 500;
}
private double calculateForOneOldCustomer(double originalPrice){
System.out.println("当前客户属于一年老客户,立减700");
return originalPrice - 700;
}
private double calculateForThreeOldCustomer(double originalPrice){
System.out.println("当前客户属于三年老客户,立减1000");
return originalPrice - 1000;
}
}
我作为客户(以主方法形式出现)当然想要自己单独写个有客户类也行
package strategy;
@SuppressWarnings("all")
public class StrategyTest {
public static void main(String[] args) {
PriceHandler priceHandler = new PriceHandler();
double discountPrice = priceHandler.dealPrice(11998, 2);
System.out.println("优惠后折扣价为:" + discountPrice);
}
}
运行结果如下:
案例代码优化思考:
思考: * 现程序扩展性不好,违背了设计的开闭原则(修改代码) * 在面向对象编程领域中,开闭原则规定"软件中的对象(类,模块,函数等等)应该对于扩展是开放的, * 但是对于修改是封闭的",这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。 * 该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查, * 单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变, * 因此无需上述的过程。 * 由此分析,如果此时多了一种身份(老客户达5五年,立减2000) * 那么对于PriceHandler类而言,dealPrice方法要多加一个case, * 并且要多加一个计算该身份客户的实际支付价格的方法,改变了源代码 * 这对于程序的可扩展性是不好的,违背了设计的开闭原则 * 因此可以用到策略模式,dealPrice方法不做判断了,传递int身份改为传递Strategy策略 * 让策略来做价格的计算,不同的客户身份有不同的计算策略 * 使用策略模式后,对于新增的客户身份的计算方式,只需要多加一个类而已,不需要修改源代码
优化后的案例代码:
策略规则,只要你是计算实际支付价格的策略就要遵循该规则
package strategy;
public interface Strategy {
double calculateDiscount(double originalPrice);
}
新客户的实际支付价格计算策略
package strategy;
public class NewCustomerStrategy implements Strategy {
@Override
public double calculateDiscount(double originalPrice) {
System.out.println("当前客户属于新客户,立减500");
return originalPrice - 500;
}
}
一年老客户的实际支付价格计算策略
package strategy;
public class OneOldCustomerStrategy implements Strategy {
@Override
public double calculateDiscount(double originalPrice) {
System.out.println("当前客户属于一年老客户,立减700");
return originalPrice - 700;
}
}
三年老客户的实际支付价格计算策略
package strategy;
public class ThreeOldCustomerStrategy implements Strategy {
@Override
public double calculateDiscount(double originalPrice) {
System.out.println("当前客户属于三年老客户,立减1000");
return originalPrice - 1000;
}
}
此时的价格处理类就变为:
此处策略可以通过方法参数传递use a关系 也可作为属性通过构造方法传递has a关系
package strategy;
@SuppressWarnings("all")
public class PriceHandler {
private Strategy strategy;
public PriceHandler(Strategy strategy){
this.strategy = strategy;
}
public double dealPrice(double originalPrice) {
System.out.println("价格处理中......");
double res = strategy.calculateDiscount(originalPrice);
System.out.println("价格生成中......");
return res;
}
public PriceHandler(){}
public double dealPrice(double originalPrice, Strategy strategy) {
System.out.println("价格处理中......");
double res = strategy.calculateDiscount(originalPrice);
System.out.println("价格生成中......");
return res;
}
}
我客户(主方法)
package strategy;
@SuppressWarnings("all")
public class StrategyTest {
public static void main(String[] args) {
Strategy strategy = new ThreeOldCustomerStrategy();
PriceHandler priceHandler = new PriceHandler(strategy);
double discountPrice = priceHandler.dealPrice(11998);
System.out.println("优惠后折扣价为:" + discountPrice);
}
}
运行结果
运行结果跟优化前差不多,只不过通过使用策略模式后,整个程序的扩展性变好了,这从长远来看是很有必要的
策略模式总结:
策略模式应用场景:
由此也可以知道官方的解释的意思了:
一个类的行为或其算法可以在运行时更改:本案例中对应的就是dealPrice方法
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法:这里的context对象在本案例中对应的就是PriceHandler的类对象,策略对象就是NewCustomerStrategy,OneOldCustomerStrategy,ThreeOldCustomerStrategy这三个策略类的对象
看完了的小伙伴们是不是对策略模式有了更深刻的理解呢?希望这篇文章能帮到小伙伴们更好的理解策略模式的设计思想,而不是使用 if,else或者switch这种不符合设计规范的写法
之后开始慢慢的更新每一种设计模式,通过生动形象的生活现象举例带你感受设计模式的世界,其实设计模式不难,只是当我们面对某个场景时想不到用哪个设计模式该不该用设计模式,怎样用才更合理… 博客内容来自腾讯课堂渡一教育拓哥,以及自己的一些理解认识,同时看了其他大牛写的设计模式技术文章综合总结出来的
|