设计原则--开闭原则
大约 2 分钟
我是Ant,今天学习的是设计原则之一的开闭原则(Open Closed Principe, OCP)。
什么是开闭原则?
开闭原则的定义是:对修改关闭,对扩展开放。 开闭原则是最基础的设计原则。
为什么使用开闭原则呢?
我们假设一个场景:程序员小A开发了一个查询年月日的项目,别人可以直接使用他的Jar调用对应的接口查询。
有一天小A将这个接口修改了,不再返回年月日,而只返回年。那么使用的人如果升级了这个Jar之后,业务逻辑是不是就出现问题了呢?
如果小A想要一个只返回年的接口,那么他可以新增加一个,这样既不影响原业务逻辑,也扩展了新功能。
所以我们要对修改关闭,对扩展开放。
示例
假设我们有一个商品对象,商品包含了价格、名称等。
public class Goods{
private String name;
private Double price;
Goods(String name, Double price) {
this.name = name;
this.price = price;
}
public void getPrice() {
return price;
}
public void getName() {
return name;
}
}
现在有了一个新业务,我们需要对商品进行打折,如果我们直接修改getPrice(), 那么我们可能再需要原价的时候就没有了入口,或者修改再修改代码,这样做系统明显不健壮,也不符合开闭原则:
public void getPrice() {
return price * 0.6;
}
那么符合的做法是什么呢? 原接口不变,新增一个接口?
public void getDiscountsPrice(){
return price * 0.6;
}
如果这么做的话,看起来是符合的,但我们需要去修改对应的业务逻辑,比如:
public class GoodsTest{
public static void main(String[] args) {
Goods goods = new Goods("苹果", 5.0);
int num = 5;
System.out.println("买了" + num + goods.getName() + ", " +
"总价:" + getTotalPrice(goods, num));
}
/**
* 查询购买指定数量的商品总价
*/
public static Double getTotalPrice(Goods goods, int num) {
return goods.getPrice() * num;
}
}
这种情况下,我们就需要将每个goods.getPrice()修改成goods.getDiscountsPrice(), 上面的例子中只有一个,但如果是有很多呢?要知道就算我们不改,代码也是不会报错的,但结果却不是我们想要的了。 那么有没有更好的办法呢? 使用继承,不修改原对象,在新对象中修改价格
public class GoodsDiscounts extends Goods {
GoodsDiscounts(String name, Double price) {
super(name, price);
}
public Double getPrice() {
super.getPrice() * 0.6;
}
public Double getOriginPrice() {
super.getPrice();
}
}
这样我们只需要将GoodsTest中的new Goods修改即可
Goods goods = new GoodsDiscounts("打折苹果", 5.0);
这样就万事大吉了...吗? 其实不然,这里虽然暂时符合了开闭原则,但违背了另一个原则:里氏替换原则。
那么具体怎么操作让上面的代码都符合呢?我们下回分解。