类设计的5个基本原则

标签: 设计 基本原则 | 发表时间:2013-03-15 11:49 | 作者:weiwenhp
出处:http://blog.csdn.net

我们常说啥面向对象三大特性:封装,继承,多态.另一种说法是:抽象,继承,动态绑定

然后就是面向对象五大设计原则,面向对象的设计其实说到底就是类的设计嘛,没有了类就自然不能叫面向对象了.当然了像C#中还有所谓的接口(interface),把它理解成一个特殊的类好了.

我觉得 面向对象的应用中最难的就是类的设计,怎么设计好一些类没有固定标准,只有一些参考原则.所以设计类不只是技术活,而且是个艺术活.

类设计(或者面向对象设计)五大基本原则

 

(1)单一职责原则(Single-Resposibility Principle)与 接口隔离原则(Interface-Segregation Principle)

 

单一职责原则

一个类尽量只做一件事.不过什么叫一件事?

就像维特根斯坦说世界可以分解为事实,而事实又分解为原子事实,原子事实(由对象组成)不可再分.那这里很明显的就是我们无法有一个标准来确定啥是原子事实.有些人觉得一个原子事实实际上可以再分,另一些人可能觉得不可分.

所以单一职责我们别指望去精确的确定啥是一件事,一个类的界限.反正就这样简单的理解.通过一个类名我们凭常规思维来想象下它可能会具有的静态属性(成员变量),动态属性(成员函数).就像我们平时看到一个名词时会联想到跟该名词紧密相关的性质.

要举个体现单一职责原则的最常见的例子无疑就是STL中的迭代器的设计.

有些人觉得容器跟迭代器的分离是不好的设计,觉得添加了复杂度.还不如直接把迭代器放容器里更简洁.不过很多人还是不这样认为的.首先嘛类的数量越多并不代表就越复杂.另外嘛迭代器如果放到容器里面,就会暴露容器的一些内部结构,不太符合封装性的思想.还有就是可扩展性的问题.因为对容器的访问遍历会有多种需求,如果把迭代器隔离开来你可以不修改容器类,再定义些特制的迭代器就行了.这样不管你有啥奇怪的需求只要整个对应的迭代器出来就OK.

 

接口隔离原则

接口依赖使用多个小的专门的接口,而不要使用一个大的总接口

其实简单点的讲与前面说的单一职责类似嘛.在C++中一个接口就是一个类,所以更加可以直接说要体现单一职责原理.而C#中的有专门的接口interface,和类区分开来的.而且C#中不像C++支持类的多继承,只继承接口的多继承.所以这里可以把接口理解成功能更小更特殊的类,一个接口可能就只要那么几个很少的方法就OK了.

 

(2)开放封闭原则(Open-Closed principle)与 依赖倒置原则(Dependecy-Inversion Principle)

 

开放封闭原则

开放封闭指:对扩展开放,对修改封闭.

这样听着肯定觉得很迷糊.所谓修改封闭,就是你之前设计好的类,类里面的方法等就不要去修改,比如删除掉一个类,删除掉一个函数或者改变函数的形参表啊.

所谓扩展开放,就是在不改变之前存在的类和函数的前提下你可以添加很多功能.一般是通过继承和多态来实现的.这样父类可以保持原样.只要子类中添加些新功能.

当然有时一些应用的改变导致父类中的一些函数实现细节也难免要改(细节的实现总是要跟着需求变的).所以最好的办法是面对抽象编程,比如定义一个抽象类,它只涉及到函数的声明,表明要实现哪些功能.而不涉及任何的细节.于是以后不用去修改它.而只修改或添加继承自这个抽象类的子类.实际上凡事都是相对而言的,不涉及到细节的抽象类改动的可能性小点,实际项目中我们也可能必须得修改抽象类,违反开放封闭原则.设计原则只是起指导作用,而不是起约束我们的作用.我们在大部分时候尽量遵循,但如果一些特殊情况需要特殊处理就自然不用去管啥原则了.

体现开放封闭原则的例子:

一个比较特别的例子就是C#中的扩展方法.不管是已经存在的你没法去修改的类库,还是你自己写的类.假如完全不让你去改动之前的代码,这自然是很好的体现封闭原则.那又要给原有的类扩充一些功能可咋整? 你首先想到可能是继承下那些类,然后在子类中添加些方法.但一来嘛如果是只是要简单的添加一点点功能,这样再整个类出来有点奢侈,费事了.二来嘛C#中还有些特殊的sealed类,它根本不能让你继承的. 于是C#中出现了个特殊的特性叫扩展方法.就是你在随便在哪定义一个静态函数,把你想扩展的类的类名作为参数,前面记得加个this.这样一来你定义的函数就会"绑定"到了那个类上.就仿佛那个类多了个函数了,实例化一该类就能调用该函数了.比较有趣的一个功能吧.C++中是没有这功能的.

 

 

依赖倒置

依赖倒置指依赖于抽象,高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象.

是不是听着有点云里雾里的啊.先来举个例子瞧瞧,假如你毕业要去找工作了,你可能要依赖某个技能吧,于是你就靠着会C,C++,C#,Java或者matlab之类的具体技能去找工作.假如说一些企业招人也是按这样具体的要求,就是要你具体掌握某个具体的编程语言来招人.这样你找工作的人与招聘的人两者都要依赖于编程语言这个细节的底层模块.这样一依赖就会出现找工作的人选择范围太小了,招聘的人可供选择的范围也小了.

而假如把那些具体的编程语言的一些基础思想抽象出来,比如对操作系统原理,编译原理,数据结构算法等的掌握.假如学生依照这个抽象出来的技能去找工作,而招聘者也根据这些抽象点的要求来招人.于是皆大欢喜,都有很大的选择范围.

在编程中就是假如有类AA与BB,而类AA与BB互相依赖,于是比较好的方法就是把AA抽象出来一个A,BB抽象出来一个B,这样就变成A,B互相依赖了.另外AA要依赖A,继承自它并实现具体细节嘛.

依赖倒置设计可以这样来理解,依赖就是刚开始是具体的细节间互相依赖,我们要变成抽象类间的依赖,降低了耦合度.然后就是有了抽象类,继承自它的实现类也要依赖它.那倒置两字咋理解呢? 一般情况我们是先关注细节,然后根据细节抽象出来一些概括的观念出来嘛.所以按常理一般是抽象要依赖于细节的.而现在是是倒过来了,确定一个抽象类后,那些细节的实现得以抽象出来的规范为基准.不然你要继承了一个抽象类,你不完全实现它的方法的话可不让你实例化对象的啊.

 

 

(3)Liskov替换原则(Liskov-Substituion Principle)

替换原则就是子类必须能够替换其基类.

看来直貌似蛮简单啊,你甚至可能觉得这不会废话嘛.我们平时用的类都是子类可以替换基类的啊.要不然多态可咋实现呢.实际上之所以你没碰到违反Liskov替换原则的类一来嘛是因为这样的场景确实不太多,另一个就是设计好的类库肯定不会让违反替换原则的类出现.所以你实际应用中不太容易接触到替换原则啊.

下面来举个违反替换原则的特殊例子:

就是正方形与长方形的问题.我们知道正方形是一个特殊的长方形.所以可以设计两个类,正方形类继承自长方形类.

然后有两变量分别表示长和宽,有个计算面积的公式.假如计算面积的方法是virtual的,这样能实现多态嘛. 在先设定长和宽后再调用计算面积的方法.我们知道正方形是长和宽相等的.如果你设定长和宽的时候不是一样的,然后呢又是调用了正方形的面积计算公式.这样肯定就错了. 你可能会问咋这么扯蛋啊,为啥把长和宽设成不一样啊.很多设计的思想是一来为了让你方便,二来为了让你少犯错误.就是不管你怎么使用都不会出错,要出错应该是在编译时就错,让意识到哪出错了.而如果出现上面说的情况编译器是没法让你知道出错了的.

所以你这样一个正方形类继承自长方形类的设计是不好的(注意的一点是你违反了Liskov可替换原则并不是说就写的代码就出错了,只是说设计不太合理.实际上你这样设计代码没准可以正常的跑得很好呢,如果没有出现一些特殊情况可能是一点bug也没有.只不过设计不合理为导致一些安全隐患而已)

 

 

概括地讲, 面向对象设计原则仍然是面向对象思想的体现。例如,

(1)单一职责原则与接口隔离原则体现了封装的思想,

(2)开放封闭原则体现了对象的封装与多态,依赖倒置原则,则是多态与抽象思想的体现而 .

(3)Liskov替换原则是对对象继承的规范,

作者:weiwenhp 发表于2013-3-15 11:49:20 原文链接
阅读:0 评论:0 查看评论

相关 [设计 基本原则] 推荐:

类设计的5个基本原则

- - CSDN博客编程语言推荐文章
我们常说啥面向对象三大特性:封装,继承,多态.另一种说法是:抽象,继承,动态绑定. 然后就是面向对象五大设计原则,面向对象的设计其实说到底就是类的设计嘛,没有了类就自然不能叫面向对象了.当然了像C#中还有所谓的接口(interface),把它理解成一个特殊的类好了.. 我觉得 面向对象的应用中最难的就是类的设计,怎么设计好一些类没有固定标准,只有一些参考原则.所以设计类不只是技术活,而且是个艺术活..

表单验证设计的用户体验基本原则

- - 博客 - 伯乐在线
英文原文: The Ultimate UX Design of Form Validation  来源 oschina. 几年前当我第一次看到Twitter的表单验证时很惊讶. 对用户界面呆板厌烦的你应该知道我在说什么. Twitter精心设计的分离式表单验证相当引人注意.当我输入错误时右侧弹出错误提示信息, 立即就能让我消除错误.”在线验证”帮助我明白什么是正确的方向.

App设计的四项基本原则:用户都属猴

- - 创业家杂志社
创业家网  文: @Fanlee  天使湾创投投资总监. 今天手机空间又快不够,又要清理App,然后一个个看过去,看先杀谁,于是出来3个问题:1、这么多App如果真非要保留,对我个人哪些必需;2、这么多App哪些SB的让人骂娘,他们的共性在哪里,怎么避免成为用户心目中SB的代名词?;3、App产品哲学,也是所有产品服务的设计哲学究竟是什么?.

程序设计的一些基本原则

- - 编程语言 - ITeye博客
本文将对本人在程序设计方面的一些思考,逐步罗列在这里. note: 此类文章/书籍,多如牛毛. 对比它们,本文并不会出现什么新的概念、思路,都是人家说过的,总结过的. 如有侵权,请指出,我将给出引用. note: 它是我在工作中的一些问题/思考总结,附上一些实际的例子(经历过才更有感触). note::“想的太多,行动太少” 是大忌.

面试基本原则

- mazhechao - Reborn
到了这个阶段,很多本科申请者都要接受面试考验了. 以下向同学们分享一下几个重要的面试基本原则. 无论是谁,都会告诉你第一印象很重要. 然后紧接下来的建议就是“衣着得体”. 但,我一直觉得“衣着得体”是个很含混的要求. 在每个人的眼里,“得体”的标准是不一样的. 不过,倒是有一个小的建议很重要:全身上下颜色越少越好.

着陆页优化基本原则

- 章明 - 互联网的那点事
坚持基本原则,能让你把一个糟糕的着陆页,变成人们很难指指点点的着陆页. 在你起步时就有力地应用它们,然后再通过钻研后面讨论的内容,改进你的页面. 把人送往一个相关而且定向的页面. 你的首页是一种面向目标传播的混合——通常以好的理由来说. 了解了这一点,就要阻止把人们送往那里的欲望,因为首页更好地定向于好奇的浏览类型,而不是人们从一个横幅和AdWords链接的点击进入.

做人四项基本原则

- Alfred.zhang - 新企业家网
①不要盘算太多,要顺其自然,该是你的终会得到. ②压抑自己没必要,奉承巴结也没必要,保持应有的人格力量将赢得更多机会和尊重. ③不要对谁特别好,也不要对谁特别不好,永远不要被少数人所利用. ④相信自己比依赖别人重要,用尽心机不如静心做事. 还想再多看几篇可能感兴趣的文章:. 有时一个人为不花钱得到的东西付出的代价最高.

问题解决型沟通(肆):基本原则

- Tim - 透明思考 - Thoughts
一次通常的多人参加的沟通,有一些基本的原则,我把它叫做“SOFT原则”:. Subject:每次沟通应该有且仅有一个主题. 如果有多个主题,也许需要不同的人、不同的时间、不同的方式. One conversation:任何时间仅有一个人在说话,其他人应该听这个人说. Facilitator:应该有一个主持人.

着陆页优化101招-第1章基本原则

- Dynamic - 所有文章 - UCD大社区
坚持基本原则,能让你把一个糟糕的着陆页,变成人们很难指指点点的着陆页. 在你起步时就有力地应用它们,然后再通过钻研后面讨论的内容,改进你的页面. 把人送往一个相关而且定向的页面. 你的首页是一种面向目标传播的混合——通常以好的理由来说. 了解了这一点,就要阻止把人们送往那里的欲望,因为首页更好地定向于好奇的浏览类型,而不是人们从一个横幅和AdWords链接的点击进入.

Linux性能分析和调整的基本原则 --zt

- flychen50 - DBA eyes
优化linux系统需要考虑多方面的因素,因为各个因素之间相互关联,因此遇到性能问题以及性能的调节需要综合考虑,基本要素考虑与分析:. 3)对磁盘进行优化(包括文件系统),提高I/O吞吐量;. 2,影响系统性能的一般因素:. 一般来说,现在的网络服务器针对提供的服务,其CPU速度是足够提供处理能力的;所以.