开闭原则
定义:
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
也就是说,如果修改或者添加一个功能,应该是通过扩展原来的代码,而不是通过修改原来的代码。
举个例子,一本书有价格,书名,年份,程序表示就是:
图解:
用代码表示为:
先创建一个图书馆接口:
public interface Library {
double getPrice();
String getBookName();
String getYear();
}
创建书类实现它:
public class Book implements Library{
private double price;
private String bookName;
private String year;
public Book(double price,String bookName,String year){
this.bookName = bookName;
this.price = price;
this.year = year;
}
public double getPrice() {
return price;
}
public String getBookName() {
return bookName;
}
public String getYear() {
return year;
}
}
然后购买书:
public class BuyBook {
public static void main(String[] args) {
Library book = new Book(100.0,"java开放原则","2008");
System.out.println("书名:"+book.getBookName());
System.out.println("价格:"+book.getPrice());
System.out.println("年份:"+book.getYear());
}
}
运行结果:
到这里都没有没有问题,但是问题自己来了,假如说今天是读书日,图书都8折出售,怎么办?
当然是赶紧修改啊,但是,假如说修改了getPrice()方法,那恢复原价了是不是还要改,以后再打折是不是还要改,这明显就违背了开闭原则的修改关闭。那么怎么修改呢,当然是扩展了!
做了如下改变:
首先添加一个子类继承图书类,在其中打折,但是要遵守里氏替换原则,所以添加一个方法:
public class BookSell extends Book{
public BookSell(double price, String bookName, String year) {
super(price, bookName, year);
}
public double getUserPrice(){
return (double) (getPrice()*0.6);
}
}
购买类:
public class BuyBook {
public static void main(String[] args) {
Library book = new BookSell(100.0,"java开放原则","2008");
System.out.println("书名:"+book.getBookName());
System.out.println("价格:"+((BookSell) book).getUserPrice());
System.out.println("年份:"+book.getYear());
}
}
输出结果:
这里就扩展了它的功能,而其它功能并没有受到影响。
图解:
如何使用开闭原则
第一:抽象约束
抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而 变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义:
- 通过接口或抽象类约束扩散,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法。
- 参数类型,引用对象尽量使用接口或抽象类,而不是实现类,这主要是实现里氏替换原则的一个要求
- 抽象层尽量保持稳定,一旦确定就不要修改
第二:元数据(metadata)控件模块行为
编程是一个很苦很累的活,那怎么才能减轻压力呢?答案是尽量使用元数据来控制程序的行为,减少重复开发。什么是元数据?用来描述环境和数据的数据,通俗的说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。
第三:制定项目章程
在一个团队中,建立项目章程是非常重要的,因为章程是所有人员都必须遵守的约定,对项目来说,约定优于配置。这比通过接口或抽象类进行约束效率更高,而扩展性一点也没有减少。
第四:封装变化
对变化封装包含两层含义:
(1)将相同的变化封装到一个接口或抽象类中
(2)将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。
封装变化,也就是受保护的变化,找出预计有变化或不稳定的点,我们为这些变化点创建稳定的接口。
上一篇: 朱见深为什么要给朱祁钰平反?
下一篇: 华为:鸿蒙OS绝不是拷贝安卓、iOS