开闭原则

Posted hhd-shuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开闭原则相关的知识,希望对你有一定的参考价值。

什么是开闭原则(Open Closed Principle)?

定义:软件实体应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

描述:

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。

下面我们来看下不符合开闭原则的案例

假如某商家要进行促销活动,他的顾客中只要是办了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折优惠,要实现这个功能,我们不得不对原有的代码进行修改。修改的幅度也会很大。也就不符合开闭原则。

 

下面我们用策略模式对代码进行修改,使其符合开闭原则

开闭原则如何实现?

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在Java、C#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

 

不管是普通用户、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 Map<Integer, DiscountStrategy> strategyMap = 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

以上是关于开闭原则的主要内容,如果未能解决你的问题,请参考以下文章

开闭原则

设计模式软件设计七大原则 ( 开闭原则 )

设计模式六大原则:开闭原则

大话设计模式读书笔记——开闭原则

设计模式六大原则:开闭原则

开闭原则