设计模式学习1 - 设计原则

9 篇文章 0 订阅

设计模式的用武之地

农科院的这个项目最严峻的任务其实就是软件复用和维护的问题。面向对象设计原则和设计模式就是解决这个问题的正解。同时所谓敏捷开发对需求修改的欢迎态度,也来自面向对象设计原则和设计模式的应用。
今天听了王总的一席话后,对软件的复用和维护的重要价值有了全新的认识,回来又认认真真的读了一下Java与模式。面向对象真是好东西啊。抽象的层次越接 近于业务逻辑越适于复用,面向对象就在面向过程基础上提高了抽象层次,同时提供了多态这样一个有利武器。SOA又在对象之上又增加了一层,封装的层次直逼 业务流程。

导致系统腐烂的原因:

需求不断的变化,增加。需求的变化导致对系统的修改,系统在修改中腐烂(尽管当初系统被设计的很完美,但是经过不断的修改,美女被改成了丑八怪)。

导致系统腐烂的根本因素:
僵硬(增加一个新的特性可能要修改多个模块) 脆弱(修改一处,多处被破坏) 低复用 粘度高(鼓励程序员破话最初的设计框架的系统--更改原来的框架来适应需求的变化付出的代价相对非常小,而维持原有框架的代价非常高,粘度高)

设计的目标:
可扩展性--加入一个功能不会影响其他模块(插入鼠标)
灵活性--修改一个模块不会导致其他模块出错(修鼠标)
可替换性--抽取一个功能模块,用实现了相同接口的模块来替换不会导致系统其他模块错误(换鼠标)

面向对象与软件复用&可维护性
多态--使得实现和应用的可复用
抽象和封装--保持和促进系统的可维护性
复用的焦点从算法、数据结构上升到更高的层次,(复用的粒度越接近业务逻辑,软件越容易维护--抽象和复用的层次更加稳定

抽象和实现相互独立性“
如果抽象层次的模块相对独立于具体实现层次的模块,具体实现层次模块的修改就不会影响抽象层次,那么抽象层次的复用就更加容易

在面向对象的设计里面,可维护的复用是以设计原则和设计模式为基础的

对可维护性的支持
依赖倒置--依赖于接口而不是具体的类: 客户端依赖一个抽象的接口而不是具体的类,使得这个类可以被另一个实现了该接口类替换。
最少知识--一个类尽可能少的与其他的类进行通信 :那么当这个类进行修改的时候就不用对其他的类造成压力

开放-封闭及其与其他原则的关系

 

可维护的复用是我们的最终目的。

开放-封闭原则
:对扩展开放,对修改封闭。看似矛盾但是其实各有所指--可以更改的是系统的实现层,不允许更改的是系统的抽象层。
在Java中抽象层由接口和抽象类来构成,但是要做到开放封闭原则那么在构件抽象层的时候就要预见所有可能的扩展。
如何实现开放-封闭
   开放-封闭原则,换个角度讲也可以讲做 封装变化原则(据说是设计模式的主题--所有的设计模式都是对不同的可变性的封装,从而使系统在某种角度上达到开-闭) :考虑我允许什么发生变化,而这变化又不会导致系统重新设计。
(1) 一种变化不应该散布在代码的很多个角落里,而应该被封装在一个对象里。同一种可变性的不同表象对应着同一个继承等级中的具体子类。继承应当被当作是封装变化的方式,而不是从一般的对象派生特殊对象的方式
(2) 一种可变性不应该与另一种可变性混合在一起。集成层次越多,可变性的混合就越多
如果能够一直坚持封装变化的设计,这样设计出系统就应当遵循开放-封闭原则。尽管很多情况下不能够百分之百的做到开放-封闭,但是一直在这个方向努力,也可以显著的改善一个系统的结构。

开放封闭与其他设计原则的关系
做到开放-封闭不是容易的事情,一些其他的设计原则是 实现开-闭的手段和工具。 违反以下原则的设计会导致对开放-封闭的远离。

里氏替换原则 :任何出现基类的地方子类一定可以出现。
依赖倒置原则 :依赖抽象而不是依赖实现。是实现开放封闭的手段。
聚合复用原则 :尽量使用聚合,而不是使用继承来实现复用的目的。
迪米特法则 :一个软件实体应该尽可能少的与其他实体发生关系。(一个模块的修改压力尽量少的传递给其他模块,更容易的对修改封闭)
接口隔离原则 :为客户端提供尽可能小的接口。(缩小通信的宽度,也是减少一个模块的修改对其他模块的压力)

多态性污染与接口的意义

 

多态性污染

 

将条件转移的代码重构成为多态性的 类,这是一个很通用的代码重构的方法,但是,并不是所有的代码都需要这种重构,否则程序设计语言就没有必要保留条件转移语句了。判断是否应该进行这种重构 的依据是,一个条件转移语句是否封装了一个业务逻辑,是否可能会随之时间的变化而变化。如果滥用多态性,就是不必要的浪费,也就是“多态性污染”。

 

重要提醒

实现开放封闭原则的一个必要条件,就是在设计抽象层的时候要尽可能考虑到将来可能的扩展,尽可能的包括将来可能的所有的扩展所需要的方法和常量。

 

接口的意义

如果不是用接口,对象与对象之间的交互就有可能是建立在对对方的行为的了 解上(硬编码),这种耦合方式使得可插入性几乎为0.如果要加入一个新类,仅仅意味着加入新的硬编码,而不能实现动态插入。抽象类也能在一定程度上解决硬 编码的问题,但是对于单继承的Java而言,还是需要接口来横向扩展。系统越大,接口的重要性越大 ,接口对系统的灵活性,可扩展性,可插入性有重要意义。

 

使用接口来声明类型

Java开发人员应该主要使用接口或抽象类将软件单位的内部和外部联系起来。也就是尽可能的使用接口而不是具体的类来声明类型,参量和返回类型,以及数据转换类型。在理想情况下,一个类应该仅仅实现接口和抽象类中规定的方法,而不应该给出多余的方法。(如果给出多余的 public 方法,那么其他的对象在与其交互的时候可能就会依赖这些方法,以致其不可替换)

 

接口的其他常用方法

单方法接口:

函数指针允许C程序有跳转的能力,单方法接口的用意很类似。如Runnable

 

标识接口:

没有任何的属性和方法,仅仅表明实现它的类属于某种类型。如Serializable和Remote(不推荐经常使用)

 

常量接口:

(这种做法是错误的,不要使用,如果实在不想写前缀可以使用静态引入)

 

广义的迪米特法则

 

广义的迪米特法则 -- 限制对象之间的信息流量,尽可能少的开放权限。

通过方法访问数据的好处是 :当设计师在需要的时候,可以对返回的数据进行进一步的封装。(允许变化)

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值