内聚与耦合
简单理解一下内聚和耦合。
什么是模块
模块就是从逻辑上将系统分解为更细微的部分,分而治之。
复杂问题因为复杂性的问题,比较难解决,但是可以将复杂问题拆解为若干简单问题,逐个击破地解决这些简单问题,最后实现解决复杂问题的效果。
模块的粒度划分可大可小,可以是函数,类或功能块等等。
耦合主要描述的是模块与模块之间的关系,内聚则主要描述的是单个模块的内部构成。
什么是耦合
如果模块之间存在依赖,则可能会导致一个模块的改动影响了另外的模块的问题,甚至是相互影响。
两个模块之间的关系越紧密,耦合就越强,模块的独立性就会越差。
比如一个模块A直接操作了模块B中数据,则视为强耦合;若A只是通过数据与模块B交互,则视为弱耦合。
独立的模块便于扩展、维护和单元测试,如果模块之间重重依赖的话,就会极大降低开发效率。
什么是内聚
一个模块应当尽可能独立完成某个功能,模块内部的元素关联性越强,则内聚越高,模块单一性就越强。
如果有各种场景需要被引入到当前模块,代码的质量将变得非常脆弱,这种情况建议拆分为多个模块。
低内聚的模块代码,不管是维护、扩展还是重构都相当麻烦。因为要兼顾内部元素的关联性,如果不理清楚的话可能会难以下手。
接口设计原则
好的接口应当满足设计模式六大原则,很多的设计模式或框架都是基于高内聚低耦合这个出发点的。
1.单一职责原则:一个类只负责一个功能领域中的相应职责。
2.开闭原则:一个软件实体应当对扩展开放,对修改关闭。
3.里氏代换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象。
4.依赖倒转原则:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
5.接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些它不需要的接口。
6.迪米特法则: 一个软件实体应当尽可能少地与其他实体发生相互作用。例如外观模式,对外暴露的是统一接口。
外观模式
外观模式是为系统中的多个子系统提供一致的对外调用,对客户端隐藏子系统细节,降低其与子系统的耦合。
桥接模式
JDBC中的把面向厂商的接口(Driver)和面向使用者的API(DriverManager)做了拆分隔离。
// 开发者只需要关注JDBC API, 无需关注不同数据库Driver接口实现 Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection(url, username, password);
这样,开发者只需要指定数据库的驱动类,调用的方法即API都是相同的,不会因为数据库的不同而有所区别。
适配器模式
如果引入了第三方库(Hibernate,Log4j),不应该直接在代码中继承或者使用其实体类。
应该要抽出上层统一接口,然后增加实现类,最后对外暴露接口。
// 代码与log4j强耦合, 不推荐 org.apache.log4j.Logger.getRootLogger().info("yanggb"); // 底层可以随意更换log框架 FRLoggerFactory.getLogger().info("yanggb");
这样,如果要更换log框架,只需要修改FRLoggerFactory中对log框架的引用就可以了,不需要在每个业务代码中修改。
"我曾对你心动过,但赶路要紧,我忘了说。"