面向对象设计原则
来源:互联网 发布:找不到windows update 编辑:程序博客网 时间:2024/06/05 19:41
单一职责原则
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
里氏替换原则
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
依赖倒置原则
在实际编程中,我们一般需要做到如下3点:
- 低层模块尽量都要有抽象类或接口,或者两者都有。
- 变量的声明类型尽量是抽象类或接口。
- 使用继承时遵循里氏替换原则。
依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。
接口隔离原则
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建。
采用接口隔离原则对接口进行约束时,要注意以下几点:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
迪米特法则
举一个例子:有一个集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。先来看一下违反迪米特法则的设计。
//总公司员工class Employee{private String id;public void setId(String id){this.id = id;}public String getId(){return id;}}//分公司员工class SubEmployee{private String id;public void setId(String id){this.id = id;}public String getId(){return id;}}class SubCompanyManager{public List<SubEmployee> getAllEmployee(){List<SubEmployee> list = new ArrayList<SubEmployee>();for(int i=0; i<100; i++){SubEmployee emp = new SubEmployee();//为分公司人员按顺序分配一个IDemp.setId("分公司"+i);list.add(emp);}return list;}}class CompanyManager{public List<Employee> getAllEmployee(){List<Employee> list = new ArrayList<Employee>();for(int i=0; i<30; i++){Employee emp = new Employee();//为总公司人员按顺序分配一个IDemp.setId("总公司"+i);list.add(emp);}return list;}public void printAllEmployee(SubCompanyManager sub){List<SubEmployee> list1 = sub.getAllEmployee();for(SubEmployee e:list1){System.out.println(e.getId());}List<Employee> list2 = this.getAllEmployee();for(Employee e:list2){System.out.println(e.getId());}}}public class Client{public static void main(String[] args){CompanyManager e = new CompanyManager();e.printAllEmployee(new SubCompanyManager());}}
现在这个设计的主要问题出在CompanyManager中,根据迪米特法则,只与直接的朋友发生通信,而SubEmployee类并不是CompanyManager类的直接朋友(以局部变量出现的耦合不属于直接朋友),从逻辑上讲总公司只与他的分公司耦合就行了,与分公司的员工并没有任何联系,这样设计显然是增加了不必要的耦合。按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合。修改后的代码如下:
class SubCompanyManager{public List<SubEmployee> getAllEmployee(){List<SubEmployee> list = new ArrayList<SubEmployee>();for(int i=0; i<100; i++){SubEmployee emp = new SubEmployee();//为分公司人员按顺序分配一个IDemp.setId("分公司"+i);list.add(emp);}return list;}public void printEmployee(){List<SubEmployee> list = this.getAllEmployee();for(SubEmployee e:list){System.out.println(e.getId());}}}class CompanyManager{public List<Employee> getAllEmployee(){List<Employee> list = new ArrayList<Employee>();for(int i=0; i<30; i++){Employee emp = new Employee();//为总公司人员按顺序分配一个IDemp.setId("总公司"+i);list.add(emp);}return list;}public void printAllEmployee(SubCompanyManager sub){sub.printEmployee();List<Employee> list2 = this.getAllEmployee();for(Employee e:list2){System.out.println(e.getId());}}}
修改后,为分公司增加了打印人员ID的方法,总公司直接调用来打印,从而避免了与分公司的员工发生耦合。
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。
开-闭原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- 面向对象设计原则
- n排列生成与可重集排列
- 简单的mysql存储过程
- ZOJ-1180
- 【Hibernate学习笔记】Session清空缓存与清理缓存
- 编程心得
- 面向对象设计原则
- NULL,空字符串和"\0"
- 数字三角形递归与记忆化
- 简单的无限分类中递归子栏目
- 《算法导论》笔记 第12章 12.1 二叉查找树
- 字符串移动包含
- 苹果官方请求框架
- 数据库学习小记
- 设计模式之责任链