设计模式六大原则——开闭原则、单一职责原则详解
1、开闭原则(Open Close Principle,OCP)
-
概念
开闭原则的核心是:对扩展开放,对修改关闭,其目的是提高程序的扩展性,实现热拔插,即在每次需求发生变更的时候,能够在对原有代码不进行修改的基础上拓展新的功能来达到满足需求的目的。
-
简单的小案例
卖书业务:
现有如下类
1、
Book
这个接口,里面顶一个价格,书名,作者等属性,以及基本的getter和setter方法public interface Book { String getName(); int getPrice(); String getAuthor(); }
2、
NovelBook(小说)
实现了Book
类public class NovelBook implements IBook{ private String name; //为了防止精度丢失,这里用原有的价格*100的整数来保存 private int price; private String author; public NovelBook(String name, int price, String author) { this.name = name; this.price = price; this.author = author; } @Override public String getName() { return this.name; } @Override public int getPrice() { return this.price; } @Override public String getAuthor() { return this.author; } }
3、
BookStore
书店类private static ArrayList<IBook> bookList=new ArrayList<>(); static { bookList.add(new OffNovelBook("红楼梦", 9900, "曹雪芹")); bookList.add(new OffNovelBook("侠客行", 8900, "金庸")); bookList.add(new OffNovelBook("原则", 6900, "瑞达利欧")); bookList.add(new OffNovelBook("海贼王1", 4900, "尾田荣一郎")); } public static void main(String[] args) { System.out.println("卖书的记录如下----------------------"); for (IBook book : bookList) { System.out.println("书籍名称:"+book.getName()+"\t\t作者:"+book.getAuthor()+"\t\t价格:¥"+book.getPrice()/100.0+"元"); } } }
现在,有这样一个新的需求:
因为双十一,现在需要对70元及以上的书打8折,对70元以下的书打9折,现在我们应该如何去实现这个需求呢?比较容易想到的是:①对
NovelBook
这个类中的getPrice
方法进行修改②在Book
接口中添加一个新的方法。上面这两个方法或多或少都不太合适,首先,第一个,如果修改了getPrice
方法,若在其他地方想要获取到书正常的价格就无法被满足了,这改变了原先的功能;第二个,因为在接口中添加了新的方法,因此就需要在所有实现类中都要添加这一方法,导致需要修改的地方会比较多;针对上面遇到的问题,再结合开闭原则,我们可以额外增加一个打折后的小说类OffNovelBook
,它继承了NovelBook
并且重写了其getPrice
方法,使其能够得到打折后的价格,这样一来,即满足了新的需求,且没有对原有业务产生影响代码如下:
public class OffNovelBook extends NovelBook{ public OffNovelBook(String name, int price, String author) { super(name, price, author); } @Override public int getPrice() { int sellPrice=super.getPrice(); int offPrice=0; if(sellPrice>7000){ offPrice=sellPrice*90/100; }else{ offPrice=sellPrice*80/100; } return offPrice; } }
-
总结:
优点:
1、便于软件测试
因为并没有对原有代码进行修改,因此,每次只需要对新增的代码进行测试即可
2、提高代码的可复用性
因为粒度越小,被复用的可能性就越大
3、提高软件可维护性
遵守开闭原则的软件,因为每次只是在拓展新功能不会对原先的功能产生太大影响,因此其稳定性强,从而易于维护
2、单一职责原则(Single Responsibility Principle,SRP)
-
概念:
顾名思义,即指一个类应该仅具有一个引起它变化的原因(即只与他职责相关的原因),其目的是降低复杂度,提高可读性和可维护性,试想一下,如果一个类有各种各样互不相关的方法和属性,那一定会让你眼花缭乱的,就好比,一个人身兼数职,一个人就是一支团队,这样看似简单,但是一定会让那个人很累,因要只要与其相关的事都和他有关。需要特别说明的是,因为对于职责划分这一问题,没有唯一解,因此,大家可以根据情况来决定如何划分
-
简单案例:
实现一个打电话的功能:
Phone
接口,里面定义了拨号、通话和挂断几个方法public interface Phone { //拨号 void dial(String phoneNumber); //通话 void chat(Object obj); //挂断 void hangup(); }
简单分析一下:
上面这样写的缺点:
1、当客户端只需要其中的某一个职责时,不得不把其他不需要的职责也要包含进来,造成了代码的冗余
2、某一个职责的变化可能会引起这个类实现其他职责的能力,通俗的说可能会短时间忙不过来
仔细分析,我们不难发现,拨号和挂断这两个方法是和协议相关的,通话是和数据传输相关的,因此,我们可以根据分析来划分职责:
public interface DataTransfer { void chat(Object obj); }
public interface ConnectionManger { void dial(String phoneNumber); void hangup(); }
-
总结
优点:
1、降低复杂度
一个类只负责一项职责,逻辑较简单
2、提高可读性
复杂度降低,因此可读性会提高
3、提高可维护性
随着可读性的提高,可维护性也会提高
4、因为变更引起的风险降低
根据单一职责原则,当修改某个功能时,会显著减少对其他功能的影响