设计原则是指导我们代码设计的一些经验总结,也就是“心法”;面向对象就是我们的“武器”;设计模式就是“招式”。
以心法为基础,以武器运用招式应对复杂的编程问题。
来吧,通过生活中一个小场景,一起系统学习这6大设计原则。
表妹今天上班又忘记打卡了
表妹:哥啊,我真的是一点记性都没有
我:发生什么事啦?
表妹:今天上班又忘记打卡了,又是白打工的一天,做什么事都提不起劲来。
你看,传统的上下班打卡制,这种模式将按时上下班作为考核指标之一,虽然强化了企业的管理,但是却限制了员工的时间自由,每个员工的情况和工作状态都不同,强制的上班时间容易导致员工为了应付打卡而打卡,实则工作效率却不高。
按时上下班其实不是老板希望达到的目的,老板希望的是,所有员工的绩效达标,最终企业能够盈利,而上下班打卡制只不过是为了达到这一目标的其中一个方法而已。
明确了将绩效作为考核指标。那么,绩效至少达标,这个是不可以修改的,在这个基础上,员工的上下班时间是可以自由安排的,这样就可以提高员工的生产效率了。这就是弹性上班制,对业绩成效的修改关闭,而对时间制度扩展的开放。
你看,这不就是我们软件开发中的开放-封闭原则嘛。
是说软件实体(类、模块、函数等)应该可以扩展,但是不可以修改。
这是一条最难理解和掌握,但是又最有用的设计原则。
之所以说难理解,是因为,“怎样的代码改动才被定义为扩展?怎样的代码改动才被定义为修改?怎样才算满足开闭原则?修改代码就一定违反了开闭原则吗?”等问题。
之所以说难掌握,是因为,“如何做到对扩展开放,修改封闭?,如何在项目中灵活地应用开闭原则,在保证扩展性的同时又不影响代码的可读性?”等问题。
之所以说最有用,是因为,扩展性是代码质量最重要的衡量标准之一。在23种经典设计模式之中,大部分设计模式都是为了解决代码的扩展性问题而存在的。
如何理解“对扩展开放、修改关闭”?比如,书店销售图书。
图书有三个属性:书名、价格和作者。IBook是获取图书三个属性的接口,如下所示:
1 public interface IBook { 2 // 图书的名称 3 public String getName(); 4 5 // 图书的售价 6 public int getPrice(); 7 8 // 图书的作者 9 public String getAuthor(); 10 }
小说类图书NovelBook是一个具体的实现类,如下所示:
1 public class NovelBook implements IBook { 2 // 图书的名称 3 private String name; 4 5 // 图书的价格 6 private int price; 7 8 // 图书的作者 9 private String author; 10 11 // 通过构造函数传递书籍数据 12 public NovelBook(String _name,int _price,String _author){ 13 this.name = _name; 14 this.price = _price; 15 this.author = _author; 16 } 17 18 // 获得作者是谁 19 public String getAuthor() { 20 return this.author; 21 } 22 23 // 获得书名 24 public String getName() { 25 return this.name; 26 } 27 28 // 获得图书的价格 29 public int getPrice() { 30 return this.price; 31 } 32 }
接下来,我们看一下,书店是如何销售图书的:
1 public class BookStore { 2 private final static ArrayList<IBook> bookList = new ArrayList<IBook>(); 3 4 // 静态模块初始化,项目中一般是从持久层初始化产生 5 static{ 6 bookList.add(new NovelBook("天龙八部",3200,"金庸")); 7 bookList.add(new NovelBook("巴黎圣母院",5600,"雨果")); 8 bookList.add(new NovelBook("悲惨世界",3500,"雨果")); 9 bookList.add(new NovelBook("平凡的世界",4300,"路遥")); 10 } 11 12 //模拟书店买书 13 public static void main(String[] args) { 14 NumberFormat formatter = NumberFormat.getCurrencyInstance(); 15 formatter.setMaximumFractionDigits(2); 16 System.out.println("------------书店中的小说类图书记录如下:---------------------"); 17 for(IBook book:bookList){ 18 System.out.println("书籍名称:" + book.getName()+"\t书籍