面向对象设计(OOD)核心原则让我的程序模块达到“高内聚低耦合”,这是来自于30年前兴起的结构化设计(structured Design),但是同样适用于我们的OOD。
1.高内聚:
高内聚是指某个特定模块(程序,类型)都应完成一系列相关功能,描述了不同程序,类型中方法,方法中不同操作描述的逻辑之间的距离相近。高内聚意味可维护性,可重新性,因为模块对外部的依赖少(功能的完备性)。如果两个模块之间的修改,互不影响这说明模块之间是高内聚的。模块的内聚和其担当的职责成反比,即,模块的职责越多,模块的内聚性越低,这也是模块的单一原则(SRP),SRP提倡每个类型都最好只承担单一的职责,只有单一的改变因素。
2.低耦合:
耦合是描述模块之间的依赖程度,如果一个模块的修改,都有影响另一个模块则,两模块之间是相互依赖耦合的。(依赖具有传递性,耦合的两个模块可能间接依赖),低耦合是我们的设计目的,但不是不存在耦合不存依赖,依赖是必须的,因为模块之间必须通信交互,不过我的设计依赖应该依赖于不变或者不易变的接口,无需了解模块的具实现(OO封装性)。
在面向对象:我们可以简述为功能完备(高内聚)的对象之间的交互是依赖于不变或不易变的接口契约(低耦合)。
实现高内聚低耦合:行之有效的方式是分了关注点(SOC),将系统拆分成功能不同没有重叠功能集。每个功能只关注一个方面(Aspect)保证模块之间功能没有或者尽量少的重复。模块化内部实现细节隐藏,只暴露必须的接口,使得模块之间依赖于抽象,达到稳定。分离关注点的思想存在于我们软件设计的各个领域。如在.net的世界里SOA(面向服务架构)服务就是关注点,只暴露出必要的契约。分层架构从逻辑上利用接口抽象信息隐藏,减少依赖。MVC,MVP也是遵循分了关注点原则,达到表现层和逻辑的分离。
面向对象设计原则:
1.降低耦合度:对象直接需要交互,这就存在依赖,为了实现低耦合就必须减少依赖,依赖于稳定或不易变抽象。考虑如下订单日志记录场景:我们需要在订单每部操作记录更改日志。
- public class OrderManager
- {
- public void Create(Order order)
- {
- //订单处理.
- Logger log = new Logger();
- var history=GetHistory();
- log.log(history);
- }
- }
在这里我们的OrderManager和Logger存在高耦合,Logger类的修改可能导致OrderManager的修改,而且不能随意切换我们的日志记录方式,比如文件,控制台,数据库等日志方式。
面向抽象编程提出抽象(接口,abstract类)是不易变的稳定抽象;对于OrderManager来说我不需要了解日志记录组件内部,只需要明白提供那些接口可用,怎么用。
- public interface ILogger
- {
- void Log(History history);
- }
- public class Logger
- {
- public void Log(History history)
- {
- //内部实现
- };
- }
那么我们可以从设计模式工厂模式(工厂模式是负责一些列相似对象的创建)Create 日志组件ILogger。
我们的OrderManager 就可以实现为:
- ILogger log =LoggerFactory.Create();
- log.Log(history);
这样我们的OrderManager就依赖于ILogger,而隔离Logger具体实现,将依赖于抽象,把变化缩小到Factory内部(同样也可以用抽象工厂),如果日志实现变化我们可以重新实现ILogger ,修改