概述
开闭原则是编程中最基础、最重要的设计原则。
一个软件实体(类、模块、方法等)应该对扩展新功能开放,对修改原有功能关闭。用抽象构建框架,用实现扩展细节。
当软件需要添加一个功能时,尽量在原有代码基础上进行扩展,而不是修改原有代码。
案例演示
以书店销售书籍为例来说明什么是开闭原则:
public interface IBook {
String getName();
double getPrice();
String getAuthor();
}
public class NovelBook implements IBook {
private String name;
private double price;
private String author;
public NovelBook() {
}
public NovelBook(String name, double price, String author) {
this.name = name;
this.price = price;
this.author = author;
}
@Override
public String getName() {
return this.name;
}
@Override
public double getPrice() {
return this.price;
}
@Override
public String getAuthor() {
return this.author;
}
}
public class BookStore {
public static void main(String[] args) {
NovelBook nb = new NovelBook("天龙八部", 95, "金庸");
System.out.println(nb.getName());
System.out.println(nb.getPrice());
System.out.println(nb.getAuthor());
}
}
假如到了双十一,要搞打折活动,40元以上书籍大九折,80元以上书籍打八折。需要修改程序适应需求的变化
违反开闭原则的方案:
修改NovelBook类,直接在getPrice()方法中实现打折功能:
@Override
public double getPrice() {
if (this.price > 80) {
return this.price * 0.8;
}
if (this.price > 40) {
return this.price * 0.9;
}
return this.price;
}
此方案虽完成了打折销售的功能,却失去了获取原价的功能,若需要同时获取原价和打折价该如何实现?
改进方案一:
不修改现有代码,在NovelBook类中添加getDiscountPrice()方法,实现获取打折价功能:
public class NovelBook implements IBook {
private String name;
private double price;
private String author;
public NovelBook() {
}
public NovelBook(String name, double price, String author) {
this.name = name;
this.price = price;
this.author = author;
}
@Override
public String getName() {
return this.name;
}
@Override
public double getPrice() {
return this.price;
}
@Override
public String getAuthor() {
return this.author;
}
//获取打折后价格
public double getDiscountPrice() {
if (this.price > 80) {
return this.price * 0.8;
}
if (this.price > 40) {
return this.price * 0.9;
}
return this.price;
}
}
public class BookStore {
public static void main(String[] args) {
NovelBook nb = new NovelBook("天龙八部", 95, "金庸");
System.out.println(nb.getName());
System.out.println(nb.getPrice());
System.out.println(nb.getAuthor());
System.out.println(nb.getDiscountPrice());
}
}
缺点:在类级别上违反了开闭原则
改进方案二:
创建NovelBook类的子类,在子类中添加getDiscountPrice()方法 获取打折后价格:
public class DiscountNovelBook extends NovelBook {
public DiscountNovelBook(String name, double price, String author) {
super(name, price, author);
}
@Override
public double getDiscountPrice() {
double price = super.getPrice();
if (price > 80) {
return price * 0.8;
}
if (price > 40) {
return price * 0.9;
}
return price;
}
}
public class BookStore {
public static void main(String[] args) {
DiscountNovelBook nb = new DiscountNovelBook("倚天屠龙记", 60, "金庸");
System.out.println(nb.getName());
System.out.println(nb.getPrice());
System.out.println(nb.getAuthor());
System.out.println(nb.getDiscountPrice());
}
}