设计原则:
开闭原则
依赖倒置原则
单一职责原则
接口隔离原则
迪米特法则(最少知道原则)
里氏替换原则
合成、复用原则(组合、复用原则)
一个软件实体如类,模块或者函数应该对扩展开放,对修改关闭(开闭)。强调的是用抽象构建框架,用实现扩展细节。按照这个原则的优点就是提高软件的可复用性和可维护性。----面向抽象编程。
举例有个课程的设计,面向抽象编程首先课程定义成接口,课程有获取课程id,课程名称,课程价格的三个抽象方法
public interface ICourse {
public Integer getId();
public String getName();
public Double getPrice();
}
针对课程,可能会有Java课程,Go课程,PHP课程等等,因此我们会有不同的子类实现
package designpatterns.principle.openclose;
public class JavaCourse implements ICourse{
private int id;
private String name;
private double price;
public JavaCourse(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
@Override
public Double getPrice() {
return this.price;
}
}
package designpatterns.principle.openclose;
public class GoCourse implements ICourse{
private int id;
private String name;
private double price;
public GoCourse(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public Integer getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
@Override
public Double getPrice() {
return this.price;
}
}
我们编写一个测试类,来获取某个具体课程的名称,价格等:
package designpatterns.principle.openclose;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import static org.junit.Assert.*;
@Slf4j
public class ICourseTest {
@Test
public void testCourse() {
ICourse iCourse = new JavaCourse(1001, "java 编程学习", 320);
log.info("课程id {}, 课程名称{}, 课程价格{}", iCourse.getId(), iCourse.getName(), iCourse.getPrice());
}
}
一种方法我们通过修改接口,增加一个getDiscountPrice(), 但是接口一般是稳定的,不应该有大动作改动,这会带来一个问题,就是我们的所有这个接口的实例比如JavaCourse,GoCourse 都需要更改逻辑增加这样的一个方法,这就破坏了我们的开闭原则。那么我们还能怎么做呢?
定义一个新的子类,继承自JavaCourse,这时候我们就不需要改动Course接口,也不需要改动avaCourse,GoCourse,这样我们就做到了对扩展开放,对修改关闭。
package designpatterns.principle.openclose;
public class JavaDiscountCourse extends JavaCourse{
public JavaDiscountCourse(int id, String name, double price) {
super(id, name, price);
}
public Double getOriginPrice() {
return super.getPrice();
}
@Override
public Double getPrice() {
return super.getPrice() * 0.8;
}
}
测试类调整如下:
package designpatterns.principle.openclose;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import static org.junit.Assert.*;
@Slf4j
public class ICourseTest {
@Test
public void testCourse() {
ICourse iCourse = new JavaCourse(1001, "java 编程学习", 320);
log.info("课程id {}, 课程名称{}, 课程价格{}", iCourse.getId(), iCourse.getName(), iCourse.getPrice());
}
@Test
public void testCourseDiscount() {
ICourse iCourse = new JavaDiscountCourse(1001, "java 编程学习", 320);
JavaDiscountCourse javaDiscountCourse = (JavaDiscountCourse)iCourse;
log.info("课程id {}, 课程名称{}, 原始课程价格{},打折之后的价格", iCourse.getId(), iCourse.getName(), ((JavaDiscountCourse) iCourse).getOriginPrice(), iCourse.getPrice());
}
}