开闭原则(Open Close Principle)
- 开闭原则的定义:
一个软件实体如类、模块或函数应该对扩展开放,而对修改关闭 - 基本概念
- 开:面向扩展开放
- 闭:面向修改关闭
开闭原则其实就是让我们遵循一种编码习惯,尽量通过扩展软件实体的行为来实现对软件的改进变化,而不是通过修改现有的代码来完成这种功能。
- 优点
遵循开闭原则的系统,要有更好的灵活性、可复用性,维护起来也更加方便。 - 例子:以商品为例进行开闭原则的说明
public interface Product {
/**
* 获取商品名称
* @return
*/
String getName();
/**
* 获取商品价格
* @return
*/
Double getPrice();
/**
* 获取商品类型
* @return
*/
Integer getType();
}
public class AProduct implements Product{
/**
* 商品名称
*/
private String name;
/**
* 商品价格
*/
private Double price;
/**
* 商品类型
*/
private Integer type;
/**
* @param name
* @param price
* @param type
*/
public AProduct(String name, Double price, Integer type) {
super();
this.name = name;
this.price = price;
this.type = type;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
@Override
public Double getPrice() {
// TODO Auto-generated method stub
return price;
}
@Override
public Integer getType() {
// TODO Auto-generated method stub
return type;
}
public static void main(String[] args) {
AProduct aProduct=new AProduct("笔记本", 9999.9, 1);
System.out.println("商品名称:"+aProduct.getName()+"\n"
+"商品价格:"+aProduct.getPrice()+"\n"
+"商品分类:"+aProduct.getType());
}
}
商品正常销售,但遇到节假日需要做一些促销活动来吸引更多的购买者。
如对商品进行打折活动。那么问题来了,打折这一动作,对应到代码中就是编码的变化,
我们要做的就是如何调整或者扩展代码来解决问题,一般来说,要做如下动作:
1. 修改接口
-
在上边的商品接口中添加一个商品打折的方法
getDiscountPrice()
,来获取打折之后的商品价格。
如果采用这种方法,就会产生如下问题:Product
接口不应该经常被修改,否则接口作为一种契约也就失去了其作用- 并非所用的商品都打折,加入其它的实现类之后,也都会实现此接口,但是只有部分商品打折,与我们的实际需求不吻合。
所以不采用这种方法。
2. 修改接口实现类
- 直接修改实现类中的
getPrice()
方法,会导致获取商品的原价格出问题;或添加获取打折的接口,会导致获取价格上存在二义性。
所以这种方法也不采用。
3.通过扩展来实现新增需求
- 直接添加一个子类DiscountProduct,重写
getPrice()
方法,这个方案对原来代码没有任何影响,完全符合开闭原则,所以此方案可行。代码如下:
public class DiscountProduct extends AProduct{
/**
* @param name
* @param price
* @param type
*/
public DiscountProduct(String name, Double price, Integer type) {
super(name, price, type);
}
@Override
public Double getPrice() {
return super.getPrice()*0.79;
}
public static void main(String[] args) {
DiscountProduct discountProduct=new DiscountProduct("HAIER", 999.9,0);
System.out.println("商品名称:"+discountProduct.getName()
+"\n商品价格:"+discountProduct.getPrice()
+"\n商品类型:"+discountProduct.getType());
}
}
经过上述分析,采用第三种方式,即开闭原则,若是添加其他商品后,价格的变化都可以采用此种方案来解决,不仅对原生代码没有污染,而且现有代码的维护性和灵活度也相当好。