《软件设计原则》PPT课件.ppt
《《软件设计原则》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《软件设计原则》PPT课件.ppt(111页珍藏版)》请在三一办公上搜索。
1、软件设计原则,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,软件可维护性设计,一个维护中的软件是不断再生的软件。修改需求,流程、界面等细节变更,修改积累,往往导致原有软件结构混乱,软件腐烂(可维护性差,可升级性差)。系统设计师:辩解用户需求变化多;软件腐烂:过于僵硬rigidity过于脆弱fragility复用率低immobility黏度高viscosity,软件可维护性设计,软件腐烂:过于僵硬rigidity添加一个新功能,很困难,牵扯多,周期长过于脆弱fragility一个地方修改,导致其他地方出现故障,甚至不可
2、预期;复用率低immobility1、想复用A模块,但A牵扯BCDE,牵扯太多,不敢被复用;2、不同模块中的重复功能,重复实现,发现问题,重复修改。黏度高viscosity1、修改,保持原有设计;2、修改破坏原有设计如果总体设计,总是导致2的实现比1容易,就是黏度过高黏度高过会诱导程序员采用错误的方案,并导致软件逐渐腐烂,软件可维护性设计,可维护性设计目标可扩展性extensibility;加入新模块,不影响原有模块灵活性flexibility;修改一个模块,不影响其他模块可插入性pluggability可以很容易的去掉一个模块,更换一个模块,加入一个新模块,而不影响其他模块。,面向对象的设计
3、原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,软件可复用性(reuse)设计1,复用的重要性:1、较高的效率;2、较高的软件质量;3、较好的可维护性。传统的复用1、复制、剪切代码;2、算法的复用;3、数据结构的复用;传统复用,往往会破坏软件的可维护性。AB共用C,如果A要修改C,B不允许。,软件可复用性(reuse)设计2,面向对象设计的复用:数据的抽象化、封装、继承、多态。复用的焦点集中在含有宏观商业逻辑的抽象层面;而不局限于函数和算法。对可维护性的支持可扩展性extensibility;封装,继承,多态由开闭原则、里氏代换原则
4、、依赖倒转原则、组合/聚合复用保证灵活性flexibility;复用,相对独立,与其他模块松耦合。该模块修改后,不会传递到其他模块。由开闭原则、迪米特法则、接口隔离原则保证。可插入性pluggability复用后,新类替代旧类,容易实现。由开闭原则、里氏代换原则、组合/聚合服用原则和依赖倒转原则保证。,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,开-闭原则1,开-闭原则OCP:open-closed principle):一个软件实体,应当对扩展开放,对修改关闭。设计一个模块时,应当使该模块在不被修改前提下被扩展;
5、即不修改源代码,而改变该模块的行为。加个代码例子满足开-闭原则的设计的优越性:1、具备适应性和灵活性;2、稳定性和延续性;实现该原则,是在更高层次上,实现了复用的、易于维护的系统。,开-闭原则2,关键点:抽象化抽象设计:给系统定义出一个一劳永逸、不再修改的抽象设计。允许此设计有无穷无尽的行为在实现层被实现。JAVA中,抽象JAVA类或JAVA接口,规定所有具体类必须提供的方法的特征,作为系统设计的抽象层。该抽象层预见了所有的可能的扩展。因此,在扩展中,抽象层不需要修改。满足了开闭原则中“对修改关闭”的原则。同时,从抽象层导出的具体新类可以改变系统的行为,又是对扩展开放的。,开-闭原则3,关键点
6、:抽象化但往往归纳较为困难汽车的定义:按照国家最新标准GB/T 3730.12001对汽车的定义:由动力驱动,具有四个或四个以上车轮的非轨道承载的车辆,主要用于:载运人员和(或)货物;牵引载运人员和(或)货物的车辆;特殊用途。本术语还包括:a)与电力线相联的车辆,如无轨电车;b)整车整备质量超过400kg的三轮车辆。电车算汽车,马拉四轮车呢?美国汽车工程师学会标准SAEJ 687C中对汽车的定义是:由本身动力驱动,装有驾驶装置,能在固定轨道以外的道路或地域上运送客货或牵引车辆的车辆。2轮摩托车算汽车吗?日本工业标准JISK 0101 中对汽车的定义是:自身装有发动机和操纵装置,不依靠固定轨道和
7、架线能在陆上行驶的车辆。,开-闭原则3,对可变性的封装原则考虑设计中什么可能会发生变化,将其封装起来,考虑允许什么发生而不让这一变化导致重新设计。意味着:1、一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里面。同一种可变性的不同表象,意味着同一个继承等级结构中的具体子类。继承,应被看做是封装变化的方法。2、一种可变性不应当与另一种可变性混合在一起。类图的继承结构,一般不会超过两层,否则,意味着两种不同的可变性混在了一起?,开-闭原则4,策略模式与开闭原则策略模式:如果有一组算法,就将每一个算法封装起来,使之可以互换?从对可变性的封装原则出发。参考策略模式?开闭原则与java日历
8、设计?如何解决。,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,JAVA语言的接口,接口:电源插座,微波炉可以,笔记本电源也可以。如果可以动态的将一个构件移走,并以另一个构件取而代之,那么这种构件就是可插入构件。插座,即接口。电器,即可插入构件可插入构件的关键在于,存在一个公用的接口。接口是实现构件的可插入性(pluggability)的关键接口的定义:接口(interface)是一些方法特征的集合,这些方法特征来自于一些在系统中不断出现的方法。,JAVA语言的接口,接口的定义:接口(interface)是一些方法特
9、征的集合,这些方法特征来自于一些在系统中不断出现的方法。接口,只有方法的特征,而没有方法的实现,因此这些方法在不同的地方被实现时,可以具有完全不同的行为。接口,与类的最重要区别:接口仅仅描述方法的特征,而不给出方法的实现。类不仅给出方法的特征,而且给出方法的实现。接口把方法的特征和方法实现分割开来。接口,类似角色,包装与该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色可以由不同的演员来演;而不同的演员之间,除了可以扮演一个共同的角色之外,并不要求有其他任何共同之处。,JAVA语言的接口,接口的意义如果没有接口:对象是相互关联的,常常需要借助其他对象的行为,以便完成一项
10、工作。如果这种对其他对象行为的调用,是通过硬代码的形式写在类中,则可插入性几乎为零。类的继承,抽象超类,通过声明子类的行为,具体类继承超类,并以不同的方法实现了超类所声明的行为。客户端可以动态的决定使用哪一个具体的子类,具有一定的可插入性。但是,Java是单继承语言,一个类只能继承一个超类。对于子类,不可能加入一个新超类的功能,除非设置超超类,就是子类他爷爷类。但如此,子类具体功能的改变,往往导致结构上大范围的调整。,JAVA语言的接口,接口是对可插入性的保证关联:一个对象需要完成一项任务,需要知道并调用其他对象的方法,对象与其他对象的联系叫做关联。关联的可插入性:关联,调用类中的某一方法。I
11、nteger a=String.ToInteger(“12”)如果一个关联不是针对一个具体类,而是针对一个接口。那么任何实现该接口的类都可以满足要求。如此,就可以动态的将此关联从一个具体类转换到另一个具体类调用的可插入性调用:void mothed1(String a)一个对象不可避免的需要调用其他对象的方法。这种调用,如果是一个接口,则任何实现了该接口的具体类都可以被调用。而当前对象到底调用哪一个具体类的实例,则完全可以动态决定。,JAVA语言的接口,JAVA的类型控制JAVA接口和抽象类,用来声明一个新的类型:JAVA设计师,应当主要使用JAVA接口和抽象类将软件单位与内部和外部耦合起来,
12、实现松耦合。即:应当使用JAVA接口和抽象类,而不是具体类进行变量的类型声明、参量的类型声明、方法的返回类型声明,以及数据类型转换等。更好的做法,仅使用接口,甚至不使用抽象类。理想情况下:一个具体的java类,应当仅实现JAVA接口和抽象类中声明过的方法,而不应该给出多余的方法。,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,抽象类1,JAVA的两种类:抽象类:不可实例化,不能生成对象,但可以实现具体的方法。一定是用来继承的具体类:可以实例化,具体类,不是用来继承的。抽象类与子类的关系,实际是模板方法的应用。在抽象类
13、与具体类的树形结构中,树枝节点是抽象类,树叶节点是具体类。代码重构建议(如果B是A的子类,建立C,抽象类或接口),抽象类2,抽象类,应当拥有尽可能多的共同代码在一个从抽象类到多个具体类的继承关系中,共同的代码应当尽量向上移动到位于金字塔顶端抽象类中。这样,可以提供代码的复用率,由于代码在公共的超类,而不是子类中出现,在代码发生改变时,程序员只需修改一个地方,程序可维护性更好。抽象类,应当包含尽可能少的数据数据,会占用内存,而且复用率不高,所以尽量将数据向下移动,即尽量不要置于超类中,而是要置于具体类中。,抽象类3,针对抽象编程的核心思想针对抽象的编码,主要针对超类,而不是具体类的编程。重点,解
14、决代码复用问题。正确使用继承继承分为两种:类对接口的实现,接口继承;类对类的继承,实现继承。实现继承,容易被滥用。对于抽象类,尽量使用合成,而不是继承,来达到复用目的。参考“组合/聚合复用原则”,举例,抽象类4,继承复用的使用场合继承代表“一般化、特殊化”关系,抽象的基类代表一般,而衍生的具体类代表特殊。Peter Coad条件,符合该条件所有内容,才可以使用抽象类:1、子类是超类的一个特殊种类,而不是超类的一个角色。Has-A关系应当使用聚合关系;Is-A关系符合继承关系。Has-A:一个类是另一个类的角色;人-黑社会小弟,老大角色,可以互换:人,可以做黑社会小弟,某时,也可以做老大。Is-
15、A:一个类是另一个类的一种。鸟-麻雀、天鹅种类,不可以互换:鸟,不可以某时是麻雀,某时是天鹅。2、永远不会出现需要将子类换成另一个类的子类的情况。3、子类具有扩展超类的责任,而不具有置换掉、注销掉超类的责任。如果子类需要大量的置换掉超类的行为,则不适合。4、只有在分类学角度上,才可以使用继承,不要从工具类继承,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,里氏代换原则1,孙悟空的以全盖偏西游记第三回:四海千山皆拱伏 九幽十类尽除名 孙悟空被拉去阴司,大打出手,十个冥王忙说弄错了,悟空说消名。悟空亲自检阅,直到那魂字一
16、千三百五十号上,方注着孙悟空名字,乃天产石猴,该寿三百四十二岁,善终。悟空道:“我也不记寿数几何,且只消了名字便罢,取笔过来!”那判官慌忙捧笔,饱掭浓墨。悟空拿过簿子,把猴属之类,但有名者一概勾之。螟下簿子道:“了帐,了帐!今番不伏你管了!”。猛的醒来,乃是南柯一梦。才觉伸腰,只闻得四健将与众猴高叫道:“大王,吃了多少酒,睡这一夜还不醒来?”悟空道:“醒还小可,我梦见两个人来此勾我,把我带到幽冥界城门之外,却才醒悟。是我显神通,直嚷到森罗殿,与那十王争吵,将我们的生死簿子看了,但有我等名号,俱是我勾了,都不伏那厮所辖也。”众猴磕头礼谢。自此,山猴多有不老者,以阴司无名故也。美猴王言毕前事,四健
17、将报知各洞妖王,都来贺喜。不几日,六个义兄弟,又来拜贺,一闻销名之故,又个个欢喜,每日聚乐不题。,里氏代换原则1,孙悟空的以全盖偏美猴王将带“猴”名字的通通删掉,即猴子适用的,石猴、肉猴通通适用。或者说,基类适用的,子类通通适用。这就是里氏代换原则。,里氏代换原则1,里氏代换原则:一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且根本不能察觉出基类对象和子类对象的区别。两个类,一个base类,一个derived类,derived类是base类的子类。若b是基类对象,d是子类对象。如果定义method(base b),则必然可以method(d);反过来,代换不成立。即如果meth
18、od2(derived d),则method2(b)一般不成立。里氏代换原则是继承复用的基石。只有当衍生类可以替换掉基类,软件单元的功能不受影响时,基类才能真正被复用。,里氏代换原则1,JAVA对里氏代换原则的支持:基类Base,对象b;子类Sub,对象d;一般有method(Base b),则可以method(d)问题:基类Base,实现函数public run();子类Sub,是否可以实现函数private run();分析:里氏代换原则要求,凡是基类适用的地方,子类一定适用。因此,子类必须具备基类的所有接口,可以更宽,但不能少。如果method调用了b的public run(),则同样应
19、该可以调用d的run()。但如果Sub中的run定义成了private,不能被调用。此时,就会出错。所以,从里氏代换原则的角度看,Sub中的run不可能被定义为private类型。,里氏代换原则1,JAVA对里氏代换原则的支持的局限性?JAVA编译器,不能检查一个系统在实现和商业逻辑上是否满足里氏代换原则,一个著名的例子,正方形是否是长方形的子类。?,里氏代换原则1,里氏代换原则在设计模式中的体现?-需要深入学习策略模式合成模式代理模式,里氏代换原则-墨子“取譬”,墨子。小取:“白马,马也;乘白马,乘马也;骊马,马也;乘骊马,乘马也。”,里氏代换原则-墨子“取譬”,墨子。小取:“白马,马也;乘
20、白马,乘马也;骊马,马也;乘骊马,乘马也。”马市抽象的基类,白马、黑马都是马的具体子类。一只白马是白马类的实例,一只黑马是黑马类的实例。如果一个方法,适用于马,则必然适用于白马或黑马;如:ridehorse(horse aHorse)成立则ridehorse(aWhiteHorse)成立而ridehorse(aBlackHorse)也成立。即ridehorse接受aWhiteHorse、aBlackHorse作为参数。这种实现,道出了里氏代换原则的精髓。,里氏代换原则发过来不成立,反过来,意味着子类适合的,不是基类适合的。墨子。小取:“盗,人也;恶盗,非恶人也”这里,盗实际是人的角色,而非人的
21、种类,所以算作子类,并不恰当。如果说到种类(子类),则黑奴可以说,“白人,人也,恶白人,非恶人也”;同样的,“乌,鸟也,恶乌,非恶鸟也”。,里氏代换原则代码重构,代码重构,这里指设计模式的重新编写,并不是某个函数的重构。里氏代换原则讲的是基类与子类的关系。只有当这种关系存在时,历史代换关系才存在;反之,不存在。如果两个具体类之间的关系未被了里氏代换原则,则需要根据具体情况,在两种重构方案中选择一种。1、创建一个新的抽象类,作为两个具体类的基类。将具体类A和B的共同行为转移到C中,从而解决A和B行为不一致的问题。,里氏代换原则代码重构,2、将B到A的继承关系改为委派关系?具体参考合成/聚合复用原
22、则-需要继续学习,里氏代换原则代码重构,回过头来,继续看11、创建一个新的抽象类,作为两个具体类的基类。将具体类A和B的共同行为转移到C中,从而解决A和B行为不一致的问题。实例,长方形与正方形的问题。A:长方形;B:正方形;C:四边形。,里氏代换原则代码重构,如果有一个由继承关系组成的等级结构的话,那么在等级结构的树图上面所有的叶节点,都应该是具体类。而所有的树枝节点,都应该是抽象类或接口。,面向对象的设计原则,可维护性;可复用性;开闭原则接口抽象类里氏代换原则依赖倒转原则接口隔离原则合成/聚合复用原则迪米特法则,依赖倒转原则,实现“开-闭”原则的关键是抽象化,且从抽象化导出具体化的实现如果说
23、开闭原则是面向对象设计的目标的话,依赖倒转原则就是这个面向对象设计的主要机制。依赖倒转原则的主要思想:依赖于抽象,不要依赖于具体。传统过程开发,设计方法倾向于使高层次的模块依赖于低层次的模块;抽象层次依赖于具体层次。抽象层次:包含的是应用系统的商务逻辑和宏观的、对整个系统来说重要的战略性决定,是必然性的体现;具体层次:则含有一些次要的与实现有关的算法和逻辑,以及战术性的决定,带有很大的偶然性选择。具体层次的代码会经常有变动的,不能避免出现错误。,依赖倒转原则,抽象层次依赖于具体层次,使许多具体层次的细节的算法变化立即影响到抽象层次的宏观的商务逻辑,导致微观决定宏观,战术决定战略,偶然决定必然,
24、依赖倒转原则,抽象层是宏观逻辑的、战略决策的、带有必然选择性的,应该决定具体层次的具体算法、战术决策、偶然性选择。依赖倒转原则就是要把错误的依赖关系再倒转过来,依赖倒转原则,复用性和可维护性的倒转传统过程性设计中的复用性:传统的过程性设计中,复用却侧重于具体层次模块的复用,如算法的复用、数据结构的复用、函数库的复用等,都局限于具体层次模块里的复用。较高层次的结构依赖于较低层次的结构,较低层次的结构又进一步依赖于更低层次的结构。如此,较低层次上的修改,往往导致较高层次的修改,直到高层次逻辑的修改。同样,传统的做法,也强调具体层次上的可维护性,包括一个函数、数据结构等的可维护性,而不是高级层次上的
25、可维护性。,依赖倒转原则,复用性和可维护性的倒转面向对象编程中的复用性:从复用的意义上讲,抽象层次有一个应用系统最重要的宏观逻辑,是做战略判断和决策的地方,如此,抽象层次应当是较为稳定的,应当是复用的重点。传统复用侧重于具体模块和细节的复用,因此,“倒转”,是指复用应当将复用的重点放在抽象层次上。如果抽象层次上的模块相对独立于具体层次的模块的话,抽象层次的模块复用就较为容易。同样的,宏观逻辑是维护的重点,而不是相反。高层次的模块时设计者应当复用的,依赖倒转原则,三种耦合关系:两个类之间,可以有三种耦合关系零耦合:两个类没有耦合关系,就称之为零耦合;具体耦合:耦合发生在两个具体的、可实例化的类之
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件设计原则 软件设计 原则 PPT 课件
链接地址:https://www.31ppt.com/p-4861256.html