什么是开闭原则?
开闭原则(Open-Closed Principle,OCP)指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。而且实现开闭原则的核心思想就是面向抽象编程。
为什么要遵守开闭原则?
那什么是对扩展开放,对修改关闭,而我们为什么要遵守这一个原则呢?
- 对扩展开放,当有新的需求变化时,可以对现有代码进行扩展。
- 对修改关闭,当类设计完成后,可以单独工作,当有新的需求时无需对现有代码进行修改。
我们知道对于已经上线并运行稳定的软件来说,如果当新的需求修改现有代码代价是很大的,稍有不慎就会导致系统瘫痪,因为其他引用的地方是不可预知的,这就是为什么要遵守开闭原则的原因。
案例分析
比如我们有一个支付业务,支持微信、银行卡支付,我们来看下设计思路:
1、首先我们会有一个支付业务类,用来处理支付业务
2、支付业务都包含哪些业务呢?微信支付、银行卡支付,这都是支付业务要执行的操作。
3、既然我们捋清楚了业务流程,那我们直接定义一个支付业务类,里面支持微信和银行卡支付就可以了
1、支付业务类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class PaymentBusiness {
// 支付接口
void pay(int type) {
if (type == 1) {
wx();
} else if (type == 2) {
bank();
}
}
// 微信支付
void wx() {
print("微信支付");
}
// 银行卡支付
void bank() {
print("银行卡支付");
}
}
2、使用
通过实例化支付业务类,根据支付方式的不同传入对应的类型即可
1
2
3
4
5
void main(List<String> args) {
PaymentBusiness paymentBusiness = PaymentBusiness();
paymentBusiness.pay(1);
paymentBusiness.pay(2);
}
3、运行结果
1
2
3
4
Connecting to VM Service at http://127.0.0.1:54124/gZpDYK3pl5E=/
微信支付
银行卡支付
Exited
4、完整代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void main(List<String> args) {
PaymentBusiness paymentBusiness = PaymentBusiness();
paymentBusiness.pay(1);
paymentBusiness.pay(2);
}
class PaymentBusiness {
// 支付接口
void pay(int type) {
if (type == 1) {
wx();
} else if (type == 2) {
bank();
}
}
// 微信支付
void wx() {
print("微信支付");
}
// 银行卡支付
void bank() {
print("银行卡支付");
}
}
5、分析
我们发现已经实现了对应的需求,并且能完美运行,但是如果有新的一个需求就是支付业务要增加支付宝支付,那么我们可以增加一个方法,并且增加一个type调用支付宝支付就可以了。但这种情况我们就违背了开闭原则,新增一个业务需要修改的代码非常多,而且居然连支付接口也需要改,我们继续来优化代码
设计优化方案—接口抽象
在上面的案例中我们发现新增需求的时候对修改未关闭,因为我们修改了支付接口,那我们该如果在新增需求的时候而不去改动支付方法呢!答案是有的那就是通过接口抽象的形式来进行扩展,我们来看下代码
1、定义支付接口抽象类
1
2
3
4
// 支付接口抽象
abstract class Business {
void pay();
}
2、定义业务扩展类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 微信支付业务
class WxBusiness implements Business {
@override
void pay() {
print("微信支付业务");
}
}
// 银行卡支付业务
class BankBusiness implements Business {
@override
void pay() {
print("银行支付业务");
}
}
// 支付宝支付业务
class AlipayBusiness implements Business {
@override
void pay() {
print("支付宝支付业务");
}
}
3、定义支付业务类
1
2
3
4
5
6
// 支付业务类
class PaymentBusiness {
void pay(Business business) {
business.pay();
}
}
4、使用
1
2
3
4
5
6
7
void main(List<String> args) {
AlipayBusiness alipayBusiness = AlipayBusiness();
PaymentBusiness paymentBusiness = PaymentBusiness();
paymentBusiness.pay(alipayBusiness);
}
5、运行结果
1
2
3
Connecting to VM Service at http://127.0.0.1:54896/8OVI-21MOc0=/
支付宝支付业务
Exited
6、完整代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void main(List<String> args) {
AlipayBusiness alipayBusiness = AlipayBusiness();
PaymentBusiness paymentBusiness = PaymentBusiness();
paymentBusiness.pay(alipayBusiness);
}
// 支付接口抽象
abstract class Business {
void pay();
}
// 微信支付业务
class WxBusiness implements Business {
@override
void pay() {
print("微信支付业务");
}
}
// 银行卡支付业务
class BankBusiness implements Business {
@override
void pay() {
print("银行支付业务");
}
}
// 支付宝支付业务
class AlipayBusiness implements Business {
@override
void pay() {
print("支付宝支付业务");
}
}
class PaymentBusiness {
void pay(Business business) {
business.pay();
}
}
7、分析
我们通过接口抽象的形式来进行优化,这样不管以后再增加任何类型的支付业务,只需要新增一个对应的业务类(对外扩展),而不需要在改动支付接口(对修改关闭),经过优化之后我们就遵守了开闭原则,而已对代码的扩展性和维护性大大的提高。
总结
开闭原则是对扩展开放,对修改关闭,而且大部分设计模式和设计原则都是在实现开闭原则。