定义:软件实体应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。
下面我们来看下不符合开闭原则的案例
假如某商家要进行促销活动,他的顾客中只要是办了VIP的用户均可享受8折优惠,下面用代码实现一下。
首先定义一个用户类型类
public class UserType {
// 普通客户
public static final int NORMAL = 1;
// VIP客户
public static final int VIP = 2;
}
然后是计算价格
public class OrderService {
private double result = 0.0;
public double calculateDiscount(int userType, double price){
switch (userType){
case UserType.NORMAL:
result = calculateNormal(price);
break;
case UserType.VIP:
result = calculateVip(price);
break;
}
return result;
}
// 计算普通用户价格
private double calculateNormal(double price) {
return price;
}
// 计算VIP用户价格
private double calculateVip(double price) {
return price * 0.8;
}
}
我们来测试一下
public class Test {
public static void main(String[] args) {
OrderService orderService = new OrderService();
double money = orderService.calculateDiscount(UserType.VIP, 100);
System.out.println(money);
}
}
很显然VIP用户打折后是80元。
但这有没有什么问题呢?
如果某天商家的策略变了,增加了一个SVIP,SVIP用户可享受7折优惠,要实现这个功能,我们不得不对原有的代码进行修改。修改的幅度也会很大。也就不符合开闭原则。
下面我们用策略模式对代码进行修改,使其符合开闭原则
开闭原则如何实现?
不管是普通用户、Vip用户还是SVIP用户,都会对原有价格进行折扣计算,所有我们要把用户打折活动的共性抽取出来,建立一个打折策略接口,或是抽象。
public interface DiscountStrategy {
double calculateDiscount(double price);
}
不同用户具体实现自己的打折策略
public class NormalDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price;
}
}
public class VIPDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price * 0.8;
}
}
再定义一个策略管理类,对不同打折策略进行管理
import java.util.HashMap;
import java.util.Map;
/**
* 管理策略
*/
public class StrategyContext {
private static MapstrategyMap = new HashMap<>();
// 通过静态代码块初始化键值对
static {
strategyMap.put(UserType.NORMAL, new NormalDiscountStrategy());
strategyMap.put(UserType.VIP, new VIPDiscountStrategy());
}
/**
* 返回对应策略
* @param userType
* @return
*/
public static DiscountStrategy getStrategy(Integer userType){
DiscountStrategy discountStrategy = strategyMap.get(userType);
return discountStrategy;
}
}
然后测试一下
public class Test2 {
public static void main(String[] args) {
DiscountStrategy discountStrategy = StrategyContext.getStrategy(UserType.VIP);
System.out.println(discountStrategy.calculateDiscount(100));
}
}
结果是一致的。
如果我们要增加一个SVIP的打折策略,只需要在定义一个具体的类,对其初始化就可以了。
public class SVIPDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price * 0.7;
}
}
参考链接:
https://www.cnblogs.com/az4215/p/11489712.html