面向对象编程的七大原则
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
⾯向对象编程的七⼤原则
转载⾃:
下⾯的截图:主要讲述了七种设计原则定名称,定义以及使⽤的频率。
原则⼀:(SRP:Single responsibility principle)单⼀职责原则⼜称单⼀功能原则
核⼼:解耦和增强内聚性(⾼内聚,低耦合)
描述:
类被修改的⼏率很⼤,因此应该专注于单⼀的功能。
如果你把多个功能放在同⼀个类中,功能之间就形成了关联,
改变其中⼀个功能,有可能中⽌另⼀个功能,这时就需要新⼀轮的测试来避免可能出现的问题。
原则⼆:开闭原则(OCP:Open Closed Principle)
核⼼思想:对扩展开放,对修改关闭。
即在设计⼀个模块的时候,应当使这个模
块可以在不被修改的前提下被扩展。
根据开闭原则,在设计⼀个软件系统模块(类,⽅法)的时候,应该可以在不修改原有的模块(修改关闭)的基础上,能扩展其功能(扩展开放)。
扩展开放:
某模块的功能是可扩展的,则该模块是扩展开放的。
软件系统的功能上的可扩展性要求模块是扩展开放的。
修改关闭:
某模块被其他模块调⽤,如果该模块的源代码不允许修改,则该模块修改关闭的。
软件系统的功能上的稳定性,持续性要求是修改关的。
原则三:⾥⽒替换原则(LSP:Liskov Substitution Principle)
核⼼:
1.在任何⽗类出现的地⽅都可以⽤他的⼦类来替代(⼦类应当可以替换⽗类并出现在⽗类能够出现的任何地⽅)
⼦类必须完全实现⽗类的⽅法。
在类中调⽤其他类是务必要使⽤⽗类或接
⼝,如果不能使⽤⽗类或接⼝,则说明类的设计已经违背了LSP原则。
2.⼦类可以有⾃⼰的个性。
⼦类当然可以有⾃⼰的⾏为和外观了,也就是⽅
法和属性
3.覆盖或实现⽗类的⽅法时输⼊参数可以被放⼤。
即⼦类可以重载⽗类的⽅法,但输⼊参数应⽐⽗类⽅法中的⼤,这样在⼦类代替⽗类的时候,调⽤的仍然是⽗类的⽅法。
即以⼦类中⽅法的前置条件必须与超类中被覆盖的⽅法的前置条件相同或者更宽松。
4.覆盖或实现⽗类的⽅法时输出结果可以被缩⼩。
原则四:依赖倒转原则(DIP:Dependence Inversion Principle)
别名:依赖倒置原则或依赖反转原则
核⼼:要依赖于抽象,不要依赖于具体的实现
1.⾼层模块不应该依赖低层模块,两者都应该依赖其抽象(抽象类或接⼝)
2.抽象不应该依赖细节(具体实现)
3.细节(具体实现)应该依赖抽象。
三种实现⽅式:
1.通过构造函数传递依赖对象
2.通过setter⽅法传递依赖对象
3.接⼝声明实现依赖对象
原则五:接⼝分离原则(ISP:Interface Segregation Principle)
核⼼思想:
不应该强迫客户程序依赖他们不需要使⽤的⽅法。
接⼝分离原则的意思就是:⼀个接⼝不需要提供太多的⾏为,⼀个接⼝应该只提供⼀种对外的功能,不应该把所有的操作都封装到⼀个接⼝当中.
分离接⼝的两种实现⽅法:
1.使⽤委托分离接⼝。
(Separation through Delegation)
2.使⽤多重继承分离接⼝。
(Separation through Multiple Inheritance)
原则六:合成复⽤原则(CRP:Composite Reuse Principle)
核⼼思想:
尽量使⽤对象组合,⽽不是继承来达到复⽤的⽬的。
该原则就是在⼀个新的对象⾥⾯使⽤⼀些已有的对象,
使之成为新对象的⼀部分:新的对象通过向这些对象的委派达到复⽤已有功能的⽬的。
复⽤的种类:
1.继承
2.合成聚合
注:在复⽤时应优先考虑使⽤合成聚合⽽不是继承
原则七:迪⽶特原则(LOD:Law of Demeter)
⼜叫最少知识原则
核⼼思想:
⼀个对象应当对其他对象有尽可能少的了解,不和陌⽣⼈说话。
(类间解耦,低耦合)意思就是降低各个对象之间的耦合,提⾼系统的可维护性;在模块之间只通过接⼝来通信,⽽不理会模块的内部⼯作原理,可以使各个模块的耦合成都降到最低,促进软件的复⽤
注:
1.在类的划分上,应该创建有弱耦合的类;
2.在类的结构设计上,每⼀个类都应当尽量降低成员的访问权限;
4.在对其他类的引⽤上,⼀个对象对其它对象的引⽤应当降到最低;
5.尽量降低类的访问权限;
6.谨慎使⽤序列化功能;
7.不要暴露类成员,⽽应该提供相应的访问器(属性)
UML统⼀建模语⾔,java中七种设计原则
UML统⼀建模语⾔。
类与类,类和接⼝,接⼝和接⼝之间的关系。
1、实现关系(⼀个类实现⼀个接⼝)
2、泛化关系(⼀个类继承另⼀个类)
3、关联(1)、依赖关系:⼀个类是另⼀个类的⽅法局部变量,⽅法的参数或⽅法返回值。
2)、聚合关系:⼀个类是另⼀个类的属性,是整体和部分的关系。
3)、组合关系:⼀个类是另⼀个类的属性,是整体不可分割的⼀部分,是强聚合。
)
4、单⼀职责:⼀个类⽽⾔,应该仅有⼀个引起它变化的原因,永远不要让⼀个类存在多个改变的理。
⼀个类只应该做和⼀个任务相关的业务,不应该把过多的业务放在⼀个类中完成。
迪⽶特法则:
⼀个软件实体应当尽可能少的与其他实体发⽣相互作⽤。
七种设计原则总结
单⼀职责原则:⼀个类只应该做和⼀个职责相关的事情,不要把过多的业务放在⼀个类中完成。
迪⽶特法则:软件实体之间应该做到最少的交互。
不要和陌⽣⼈说话。
调⽤⽅只关⼼他需要使⽤的⽅法
接⼝隔离原则:使⽤专门的接⼝,⽐⽤统⼀的接⼝要好。
便于分⼯,在实现接⼝时,不应该看到⾃⼰不⽤关⼼的⽅法。
开闭原则:软件实体应该对扩展开放,对修改关闭。
开闭原则是设计原则的核⼼原则,其他的设计原则都是开闭原则表现和补充。
实现开闭原则的⽅法就是抽象。
聚合/组合复⽤原则。
多使⽤聚合/组合达到代码的重⽤,少使⽤继承复⽤。
⾯向对象七⼤设计原则
1、开闭原则
2、⾥⽒替换原则
3、单⼀职责原则
4、接⼝隔离原则
5、依赖倒置原则
6、迪⽶特原则
7、组合/聚合复⽤原则
知识点关联
学习⾯向对象的设计模式,是深⼊⾯向对象思想的钥匙,通过⼤师级的微妙案例,我们可以开阔⾃⼰的认知。
在学习⾯向对象设计七⼤原则之前,我们要对基本的封装、继承、多态思想有⾜够的了解,对抽象类和接⼝也要有⾜够的编码能⼒,因为设计模式是以上知识点的综合应⽤。
另外,在接触具体的设计模式之前,⾯向对象的七⼤设计原则会让你知道,设计模式出现的必然性和意义所在。
1、每⼀种设计思想的精准含义,具体如下:
先从整体认识这七种设计思想。
⼀、开闭原则:
这⼀条放在第⼀位来理解,它的含义是对扩展开放,对修改关闭。
解释⼀下就是,我们写完的代码,不能因为需求变化就修改。
我们可以通过新增代
当然,这是⼀种理想的状态,在现实中,我们要尽量的缩⼩这种修改。
再解释⼀下这条原则的意义所在,我们采⽤逆向思维⽅式来想。
如果每次需求变动都去修改原有的代码,那原有的代码就存在被修改错误的风险,当然这其中存在有意和⽆意的修改,都会导致原有正常运⾏的功能失效的风险,这样很有可能会展开可怕的蝴蝶效应,使维护⼯作剧增。
说到底,开闭原则除了表⾯上的可扩展性强以外,在企业中更看重的是维护成本。
所以,开闭原则是设计模式的第⼀⼤原则,它的潜台词是:控制需求变动风险,缩⼩维护成本。
以下⼏种原则,都是为此原则服务的。
⼆、⾥⽒替换选择:
此原则的含义是⼦类可以在任何地⽅替换它的⽗类。
解释⼀下,这是多态的前提,我们后⾯很多所谓的灵活,都是不改变声明类型的情况下,改变实例化类来完成的需求变更。
当然,继承的特性看似天然就满⾜这个条件。
但这⾥更注重的是继承的应⽤问题,我们必须保证我们的⼦类和⽗类划分是精准的。
⾥⽒替换原则的潜台词是:尽量使⽤精准的抽象类或者接⼝。
三、单⼀职责原则:
单⼀职责的含义是:类的职责单⼀,引起类变化的原因单⼀。
解释⼀下,这也是灵活的前提,如果我们把类拆分成最⼩的职能单位,那组合与复⽤就简单的多了,如果⼀个类做的事情太多,在组合的时候,必然会产⽣不必要的⽅法出现,这实际上是⼀种污染。
举个例⼦,我们在绘制图案的时候,⽤“点”组成图和⽤“直线”组成图,哪个更灵活呢?⼀定是“点”,它可以绘制任何图形,⽽直线只能绘制带有直线条的图案,它起码⽆法画圆。
单⼀职责的潜台词是:拆分到最⼩单位,解决复⽤和组合问题。
四、接⼝隔离原则:
接⼝隔离原则可以说是单⼀职责的必要⼿段,它的含义是尽量使⽤职能单⼀的接⼝,⽽不使⽤职能复杂、全⾯的接⼝。
很好理解,接⼝是为了让⼦类实现的,如果⼦类想达到职能单⼀,那么接⼝也必须满⾜职能单⼀。
相反,如果接⼝融合了多个不相关的⽅法,那它的⼦类就被迫要实现所有⽅法,尽管有些⽅法是根本⽤不到的。
这就是接⼝污染。
接⼝隔离原则的潜台词是:拆分,从接⼝开始。
五、依赖倒置原则:
想要理解依赖倒置原则,必须先理解传统的解决⽅案。
⾯相对象的初期的程序,被调⽤者依赖于调⽤者。
也就是调⽤者决定被调⽤者有什么⽅法,有什么样的实现⽅式,这种结构在需求变更的时候,会付出很⼤的代价,甚⾄推翻重写。
其实,依赖倒置和前⾯的原则是相辅相成的,都强调了抽象的重要性。
依赖倒置的潜台词是:⾯向抽象编程,解耦调⽤和被调⽤者。
六、迪⽶特原则:
迪⽶特原则要求尽量的封装,尽量的独⽴,尽量的使⽤低级别的访问修饰符。
这是封装特性的典型体现。
⼀个类如果暴露太多私⽤的⽅法和字段,会让调⽤者很茫然。
并且会给类造成不必要的判断代码。
所以,我们使⽤尽量低的访问修饰符,让外界不知道我们的内部。
这也是⾯向对象的基本思路。
这是迪⽶特原则的⼀个特性,⽆法了解类更多的私有信息。
另外,迪⽶特原则要求类之间的直接联系尽量的少,两个类的访问,通过第三个中介类来实现。
迪⽶特原则的潜台词是:不和陌⽣⼈说话,有事去中介。
七、组合/聚合复⽤原则:
此原则的含义是,如果只是达到代码复⽤的⽬的,尽量使⽤组合与聚合,⽽不是继承。
这⾥需要解释⼀下,组合聚合只是引⽤其他的类的⽅法,⽽不会受引⽤的类的继承⽽改变⾎统。
继承的耦合性更⼤,⽐如⼀个⽗类后来添加实现⼀个接⼝或者去掉⼀个接⼝,那⼦类可能会遭到毁灭性的编译错误,但如果只是组合聚合,只是引⽤类的⽅法,就不会有这种巨⼤的风险,同时也实现了复⽤。
组合聚合复⽤原则的潜台词是:我只是⽤你的⽅法,我们不⼀定是同类。
2、在学习⾯向对象七⼤设计原则时需要注意以下⼏点:
a) ⾼内聚、低耦合和单⼀职能的“冲突”
实际上,这两者是⼀回事。
内聚,要求⼀个类把所有相关的⽅法放在⼀起,初看是职能多,但有个“⾼”,就是要求把联系⾮常紧密的功能放在⼀起,也就是说,从整体看,是⼀个职能的才能放在⼀起,所以,两者是不同的表述⽽已。
这⾥很多⼈理解成复合类,但复合类不是⾼内聚,⽽是杂乱的放在⼀起,是⼀种设计失误⽽已。
b) 多个单⼀职能接⼝的灵活性和声明类型问题
如果⼀个类实现多个接⼝,那么这个类应该⽤哪个接⼝类型声明呢?应该是⽤⼀个抽象类来继承多个接⼝,⽽实现类来继承这个接⼝。
声明的时候,类型是抽象类。
这是另⼀种设计的失误。
迪⽶特原则要求类之间要⽤中介来通讯,但类多了以后,会造成中介类泛滥的情况,这种情况,我们可以考虑中介模式,⽤⼀个总的中介类来实现。
当然,设计模式都有⾃⼰的缺陷,迪⽶特原则也不是⼗全⼗美,交互类⾮常繁多的情况下,要适当的牺牲设计原则。
d) 继承和组合聚合复⽤原则的“冲突”
继承也能实现复⽤,那这个原则是不是要抛弃继承了?不是的。
继承更注重的是“⾎统”,也就是什么类型的。
⽽组合聚合更注重的是借⽤“技能”。
并且,组合聚合中,两个类是部分与整体的关系,组合聚合可以由多个类的技能组成。
在C#和Java中只有单继承。
这个原则不是告诉我们不⽤继承了,都⽤组合聚合,⽽是在“复⽤”这个点上,我们优先使⽤组合聚合。
⾯向对象设计原则的共性问题:
1、这么多设计模式,都要学习和使⽤么?
答:我们只是掌握总体的原则,然后学习常⽤的就⾏了。
实际开发中也不是每种设计模式都会经常⽤到。
因为归根结底,设计模式也好,架构也好,都是为需求服务的,没有需求业务模型,不能⽣搬硬套模式。
我们在学习的时候,多学⼀些总是好的,但只是为了开阔⾃⼰的眼界。
2、设计模式是规范么?是不是好的程序必须⽤设计模式?
答:严格来说,好的程序遵循的是设计原则,⽽⾮设计模式。
现在就出现很多新的演变出来的模式,这些都是因为出现了新业务的原因,设计模式不是规范,只是⼀种借鉴。
3、使⽤设计模式会不会增加开发难度?
答:开发阶段会的,⽽且会延长开发时间。
但⼀个项⽬或产品从开始到结束,开发只是其中很⼩的⼀部分,考虑到维护和扩展成本,才会出现设计模式。
从整体考虑,设计模式是减少了开发时间和成本的。
关于七种⾯向对象设计原则
⾯向对象设计原则是我们⽤于评价⼀个设计模式的使⽤效果的重要标准之⼀。
下⾯我给⼤家介绍⼀下七种设计原则各是什么,以及其定义:
单⼀职责原则定义:⼀个类只负责⼀个领域的相应职责
开闭原则定义:软件实体应对扩展开放,⽽对修改关闭
⾥⽒替换原则定义:所有引⽤基类的对象能够透明的使⽤其⼦类的对象
依赖倒转原则定义:抽象不应该依赖于细节,细节依赖于抽象
接⼝隔离原则定义:使⽤多个专门的接⼝,⽽不是使⽤单⼀总接⼝
合成复⽤原则定义:尽量使⽤对象组合,⽽不是继承来达到复合⽬的
迪⽶特法则定义:⼀个软件实体应当尽可能少的与其它实体发⽣相互作⽤
其中⽐较常⽤的是红⾊字体,蓝⾊字体仅次,⿊⾊字体基本不使⽤。
⾥⽒替换原则:⽗类出现的⽅法,⼦类⼀定可以替换。
如果⼦类不能完整实现⽗类⽅法,或者⽗类的⽅法在⼦类中已经发⽣了畸变,那么就要断开⽗⼦关系。
采⽤依赖、聚合、组合等关系替代继承。
⾥⽒替换原则可以⽤于检测两个类是否具有⽗⼦关系。
7种常⽤的⾯向对象设计原则
设计原则名称
定义
使⽤频率
单⼀职责原则
(Single Responsibility Principle, SRP)
⼀个类只负责⼀个功能领域中的相应职责
★★★★☆
开闭原则
(Open-Closed Principle, OCP)
软件实体应对扩展开放,⽽对修改关闭
★★★★★
⾥⽒代换原则
(Liskov Substitution Principle, LSP)
所有引⽤基类对象的地⽅能够透明地使⽤其⼦类的对象★★★★★
依赖倒转原则
(Dependence Inversion Principle, DIP)
抽象不应该依赖于细节,细节应该依赖于抽象
★★★★★
接⼝隔离原则
(Interface Segregation Principle, ISP)
使⽤多个专门的接⼝,⽽不使⽤单⼀的总接⼝
★★☆☆☆
合成复⽤原则
(Composite Reuse Principle, CRP)
尽量使⽤对象组合,⽽不是继承来达到复⽤的⽬的
★★★★☆
迪⽶特法则
(Law of Demeter, LoD)
★★★☆☆。