接口设计原则

1、单一原则

一个类只负责一个功能领域的相应职责,或者可以定义为,就一个类而言,应该只有一个引起它变化的原因。 

       单一原则的实现,完全取决于你这么抽象的看待这个问题,你抽象的合适,那么它可以很棒,如果抽象的不够,它可能就是臃肿的类,抽象的过多,有可能创造出一大把寄生类。 单一职责原则这话就像我们常听的那句"做人要坚持"。听起来无懈可击,但是要坚持什么呢,如果这事情看起来不靠谱,做着难受,我还该不该坚持呢,所以'做人要坚持'是句营养不是很足的废话。

       单一职责这话也有那么点意思。 但既然单一职责被放到设计模式的第一位,自然有其道理。所以单一模式真正的目的,其实也是设计模式的一大目的之一就是降低开发人员的脑力栈的消耗。 人脑比起电脑,没有那么深那么多得栈,所以我们在一个较短的时间内,能理解的东西是有限的,如果一次性灌输太多事务,超过其瞬时脑容量,基本后面再思考的时候就雪崩了,所以单一职责最大的准则,就是读起来越轻松越好。 而所谓读起来越轻松越好,说得比较官方一点就是:使这个类改变的因数只有唯一的一个时,那么这个类符合单一原则。

 

2、开闭原则

软件实现应该对扩展开放,对修改关闭

一个软件产品只要在生命周期内,都会发生变化,即然变化是一个事实,我们就应该在设计时尽量适应这些变化,以提高项目的稳定性和灵活性,真正实现“拥抱变化”。开闭原则告诉我们应尽量通过扩展软件实体的行为来实现变化,而不是通过修改现有代码来完成变化,它是为软件实体的未来事件而制定的对现行开发设计进行约束的一个原则。

第一:抽象约束 
抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义:

  • 通过接口或抽象类约束扩散,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法。
  • 参数类型,引用对象尽量使用接口或抽象类,而不是实现类,这主要是实现里氏替换原则的一个要求
  • 抽象层尽量保持稳定,一旦确定就不要修改

第二:元数据(metadata)控件模块行为 
编程是一个很苦很累的活,那怎么才能减轻压力呢?答案是尽量使用元数据来控制程序的行为,减少重复开发。什么是元数据?用来描述环境和数据的数据,通俗的说就是配置参数,参数可以从文件中获得,也可以从数据库中获得,同时也应该考虑数据库表的通用性和扩张性

第三:制定项目章程 
在一个团队中,建立项目章程是非常重要的,因为章程是所有人员都必须遵守的约定,对项目来说,约定优于配置。这比通过接口或抽象类进行约束效率更高,而扩展性一点也没有减少。

第四:封装变化 
对变化封装包含两层含义: 
(1)将相同的变化封装到一个接口或抽象类中 
(2)将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。 
封装变化,也就是受保护的变化,找出预计有变化或不稳定的点,我们为这些变化点创建稳定的接口。

 

3、伯斯塔尔原则

 按照伯斯塔尔法则的思想来设计实现服务调用时,发送的数据要更保守,意味着最小化的传送必要的信息,接收时更开放意味着要最大限度的容忍信息的兼容性。 多余的信息不认识可以忽略,而不应该拒绝或抛出错误。 

 

4、里氏替换原则

所有引用父类的地方,必须能透明的使用其子类对象

父类的一个方法的返回值是一个类型T,子类的相同方法的返回值为S,那么里氏替换原则就要求S必须小于等于T。采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美。

 

5、接口隔离原则

使用多个专门的接口,而不使用单一的总接口。 其实接口隔离原则说白了就是单一职责的扩展,或者说细化,将单一的概念扩展至接口,或者说具体的函数。对于一个个比较细化的接口,优点简洁且明显,那就是更小的接口,更有利于书写单元测试,也更有利于调试。

 

而如果能有比较多专门的接口,无疑会极大降低阅读理解代码的成本,阅读者往往只需要了解任务的分发逻辑就好,不需要一不小心就沉到底层繁琐的逻辑中,一个大的接口在阅读的时候,往往是任务分发逻辑和任务执行逻辑严重耦合在一起的,当你以为你在了解任务分发部分的逻辑的时候,你可能已经在读具体业务处理逻辑了。然而其实往往你根本不需要关系具体的某个功能的逻辑,多数时候,你只是需要修改一点分发逻辑。这个时候细粒度的接口就体现出优点,更为细粒度的接口,有利于隔离业务处理和业务分发的逻辑,可以提高阅读代码效率。不要小瞧这点,试想一个团队招来的新人,全部都在解决老坑的路上步履蹒跚,拖累了开发新功能进度,而这些老的东西很难再创造价值了,而能创造价值的东西,却总是在拖延中,拖过了市场,再来价值就缩水的厉害了。

 

6、合成复用原则

优先使用组合而不是继承。继承必须在is-a的关系成立的时候才能使用,否则使用组合,之所以不使用继承,是因为继承会将基类的实现细节暴露给子类,这个就导致如果基类发生改变,那么子类也不得不改变,相对而言,使用组合,可以有更好的封装性。

 

7、依赖倒置原则

抽象不依赖于细节,细节应该依赖于抽象。

在实现依赖倒转的原则的时候,我们最常使用的技术就是依赖注入(Dependency Injection,DI),通过依赖注入来对一个抽象的对象注入一个具体的实例。 对于设计模式来说,尽可能的开闭是目标,里氏替换是实现开闭的基础,而依赖倒转是具体的手段。

 

8、迪米特法则

一个软件实体应当尽可能少的与其它实体发生相互作用。 最能体现这种思想是中介者模式,在中介者模式中,各个对象之间存在通信,但是对象之间并不会互相引用,而是维持一个中介者的引用,当我们需要添加一个成员的时候,我们往往增加一个对象再修改一下中介者就好了,大部分的时候,其它对象是无感知的。 迪米特法则的好处,在于满足迪米特法则的类,通常都是可测试的类。不过想写出这样的类可不容易,这个时候可以考虑TDD的方法,不过这就是另一个话题了。

 

 

 

你可能感兴趣的:(软件设计)