定义
一个软件实体入,如类模块和函数应该对扩展开放,对修改关闭。我们应该把注意力集中在扩展开放和修改关闭这两个行为上。
扩展开放:可以扩展实现的细节,增加新的功能。
修改关闭:不修改原先定义的规则,尽量不修改源代码。
同时准寻这两个行为,即为遵循开闭原则。
开闭原则是面向对象设计中最基础的设计原则。
就比如:一个公司的上班时间是8小时,但是去上班的时间可以任意,早去上班早下班,晚去晚下班,只要满8小时就可以了。这里的8小时,就相当于修改关闭,不可以变,而早去上班早下班,晚去晚下班这个行为就是,开放的制度,可以自由选择。
核心思想
面向抽象编程
接下来我们举一个例子:
UML图
首先创建一个Interface Vegetable
需求: 具有抽象方法, 获取价格, 蔬菜名字, 生场地
Vegetable.java
public interface Vegetable {
String getName(); //get名字
double getPrice(); //get价格
String getProduceAddress(); //get生场地
}
我们需要实现一个Cabbage(白菜)类, 将接口实现
Cabbage.java
public class Cabbage implements Vegetable{
private String name;
private double price;
private String produceAddress;
public Cabbage(String name, double price,String produceAddrss){
this.name = name;
this.price = price;
this.produceAddress = produceAddrss;
}
@Override
public String getName() {
return this.name;
}
@Override
public double getPrice() {
return this.price;
}
@Override
public String getProduceAddress() {
return this.produceAddress;
}
}
那么现在我们突然需要实现一个,白菜打折活动,就需要将价格打折,那么我是应该怎么写?
思路1:可能会想到,在Vegetable接口中增加, 获取打折后的价格的方法
于是得到修改后的代码
Vegetable.java
public interface Vegetable {
String getName();
double getPrice();
String getProduceAddress();
//增加
double getDiscountPrice();
}
但以上,修改了接口的代码,将会引起实现它的子类,代码都需要修改,不符合开闭原则的修改关闭。
思路2:那么我们该如何修改。我们可以,不改动之前的代码,新建一个extends Cabbage的类,在其中增加新的功能,getOriginalPrice()方法,和Override getPrice()方法
于是演变得到
DisCountCabbage.java
public class DisCountCabbage extends Cabbage{
public DisCountCabbage(String name, double price, String produceAddrss) {
super(name, price, produceAddrss);
}
@Override
public double getPrice() {
return super.getPrice()*0.8;
}
public double getOriginalPrice() {
return super.getPrice();
}
}
这样,既没有修改原先的代码,基于原先的白菜Cabbage也扩展了新的功能,就这样遵循了开闭原则。完美
这个文件用于测试以上代码
test.java
package com.breath.design.principle.openclose;
public class test {
public static void main(String[] args) {
Cabbage cabbage = new DisCountCabbage("打折扣的白菜", 8d, "福建");
System.out.println(cabbage.getName() + "的--->价格:"+cabbage.getPrice());
DisCountCabbage disCountCabbage = (DisCountCabbage)cabbage;
System.out.println(disCountCabbage.getName()+"的--->原价:"+disCountCabbage.getOriginalPrice());
}
}