定义
类应该对扩展开放
,对修改关闭
。用抽象构建框架,用实现扩展细节。
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。如能实现这样的目标,有什么好处呢?这样的设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求。
主要特征
典型场景
在Java设计模式中,装饰者模式
是一个很好的例子,完全遵循开放-关闭
原则。
代码讲解
这里先以一个简单的例子讲解开放-关闭原则
。
第一版需求:首先抽象出一个课程
接口,然后Java,Python,UI等的课程来实现这个接口,打印出相关的课程信息。
定义一个接口Course
:
public interface Course {
/**
* 课程Id
* @return
*/
Integer getId();
/**
* 课程名称
* @return
*/
String getName();
/**
* 课程价格
* @return
*/
Double getPrice();
}
定义一个接口Course
的实现类JavaCourse
:
public class JavaCourse implements Course {
private Integer id;
private String name;
private Double price;
public JavaCourse(Integer id, String name, Double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public Double getPrice() {
return price;
}
@Override
public String toString() {
return "JavaCourse{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}';
}
}
定义测试类:
public class Test {
public static void main(String[] args) {
Course javaCourse = new JavaCourse(1, "Java课程", 100d);
System.out.println(javaCourse);
}
}
打印出如下信息:
JavaCourse{id=1, name='Java课程', price=100.0}
第二版需求:这个时候又来了一个需求,Java课程由于做活动,打8折,这个时候应该如何实现呢?
有如下几种实现方式:
Course
中,增加打折的方法getDiscountPrice()
,如下:Double getDisCountPrice();
这样JavaCourse
实现这个方法即可。
JavaCourse
类中的getPrice
方法中,直接将price*0.8。这两种方式虽然实现起来很快,但是在应对需求变化时,是明显不足的。比如:
等等。
这个时候我们可以定义个折扣类来继承自JavaCourse
,来实现对价格打折的支持,如下:
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
@Override
public Double getPrice() {
return super.getPrice() * 0.8;
}
}
然后修改测试类,如下:
Course javaCourse = new JavaDiscountCourse(1, "Java课程", 100d);
System.out.println("课程Id: " + javaCourse.getId() + ", 课程名称: " + javaCourse.getName() + ", 课程价格: " + javaCourse.getPrice());
输出如下:
课程Id: 1, 课程名称: Java课程, 课程价格: 80.0
这个时候有个问题,无法获取到原价,我们可以在JavaDiscountCourse
增加获取原价的方法,如下:
public Double getOriginPrice() {
return super.getPrice();
}
修改测试类,如下:
Course course = new JavaDiscountCourse(1, "Java课程", 100d);
JavaDiscountCourse javaCourse = (JavaDiscountCourse) course;
System.out.println("课程Id: " + javaCourse.getId() + ", 课程名称: " + javaCourse.getName() + "课程原价:" + javaCourse.getOriginPrice() + ", 课程价格: " + javaCourse.getPrice());
到此,我们的程序就修改完成了,而且不会对之前的代码有任何影响,这也就是开始提到的开放-关闭原则
。