`

面向对象七大设计原则 设计出高内聚低耦合可扩展程序

阅读更多

1.单一职责原则

        一个接口或类者只负责一项职责。

       单一职责适适用于方法,一个方法尽可能的只做一件事。 

       对于单一职责,建议一个接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化,

        一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

  好处:

       1.可降低类的复杂度,一个类只负责一项职责,其逻辑肯定比负责多项职责简单的多

        2.复杂度底,可读性自然提高。

        3.可维护性高,风险低。如果接口的单一职责好,一个接口修改只对应相应的实现类有影响。对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。  

 

 

2.里氏替换原则

       所有引用基类(父类)的地方,必须能使用其子类的对象替换 ,即:在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,

        里氏代换原则是实现开闭原则的重要方式之一,在类中调用其他类时务必要使用基类对象(父类或者接口),在传递参数,定义成员变量、定义局部变量、确定方法返回类型时都可使用里氏代换原则。针对基类编程,在程序运行时再确定具体子类。

       如果子类不能完整的实现父类中的方法,或者子类实现的父类方法,与父类方法含义不同,则建议断开父子继承关系,采用依赖、聚合、组合等关系代替继承。

        里氏替换原则通俗讲:子类可以扩展父类功能,但不能改变父类原有的功能。1.子类可以实现父类的功能,但不能改变父类原有功能 2.当子类的方法重载父类的方法时,方法的前置条件(方法形参)要比父类方法的输入参数更宽松 3.当子类方法实现父类的抽象方法,方法的后置条件(方法返回值)要比父类更严格。

        

         

 

 

 3.依赖倒置原则

        模块之间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生。

        接口或抽象类不依赖实现类(应先有接口后有实现类)。

        实现类依赖接口或者抽象类。

        依赖倒置原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。

        为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法

        依赖倒置原则即面向接口编程OOD(Object-Oriented Design):接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑。

        依赖1:构造函数传递依赖对象

        依赖2:Setter依赖注入

        依赖3:接口声明依赖对象

 

 

 4.接口隔离原则

        使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

       一个接口只服务于一个子模块或业务逻辑

        通过深入了解业务逻辑压缩接口中的public方法,达到“满身筋骨

       与单一职责原则区别,单一职责原则注重的是职责,而接口隔离原则注重对接口依赖的隔离。单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节,而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。

        接口尽量小,但是要有限度,接口细化可以提高程序设计的灵活性,但如果过小,会导致接口过多,使设计复杂化。

 

 5.迪米特法则

        问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类影响也越大。

        解决:一个软件实体应当尽可能少地与其他实体发生相互作用,迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系

      一 个类只和朋友交流,不与陌生类交流,其朋友包括以下几类:

      (1) 当前对象本身(this);

      (2) 以参数形式传入到当前对象方法中的对象;

      (3) 当前对象的成员对象;

      (4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;

      (5) 当前对象所创建的对象。

        出现在方法体内部的类不属于朋友不要出现getA().getB().getC(),除非每个点后面都返回同一个对象,类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不要引入一个类中不存在的对象。

       在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类(朋友)都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

        如果与多个朋友交互,可以通过引入一个合理的第三者来降低现有对象之间的耦合度

           迪米特法则的核心是类间解耦,只有弱耦合,类之间的复用率才可以提高,其要求的结果就是产生了大量的中转或跳转类,导致系统复杂性提高,同时也为维护带来了难度,所以在采用迪米特法则时要反复权衡,既要结构清晰,又要搞内聚低耦合。

        一般一个类访问另一个类跳转不要超过2 次。

 

6.开闭原则

       一个软件实体应当对扩展开放,对修改关闭。其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

     实体:软件模块、抽象和类、方法。

     在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑,只有这样的代码才可以复用,粒度越小,被复用的可能性就越大,复用可以减少代码量,避免相同的逻辑分散在多个角落。避免日后的维护人员为了修改一个微小的缺陷而在整个项目中到处查找相关代码。

        开闭原则可以提高维护性,扩展一个类相对修改一个类要舒服很多。

        抽象层应尽量保持稳定,一旦确定即不允许修改。接口或者抽象类一旦定义,就应该立即执行,不能有修改接口的思想。除非是彻底的大返工。

     

7.合成复用原则

    尽量使用对象组合,而不是继承来达到复用的目的。

     复用时要尽量使用组合/聚合关系(关联关系),少用继承。来使用一个已有的对象成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用功能的目的。

      在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合组合/聚合可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用

      通过继承来进行复用的主要问题在于继承复用会破坏系统的封装性,因为继承会将基类的实现细节暴露给子类,由于基类的内部细节通常对子类来说是可见的,所以这种复用又称“白箱”复用,如果基类发生改变,那么子类的实现也不得不发生改变;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;而且继承只能在有限的环境中使用(如类没有声明为不能被继承)。

       由于组合或聚合关系可以将已有的对象(也可称为成员对象)纳入到新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能,这样做可以使得成员对象的内部实现细节对于新对象不可见,所以这种复用又称为“黑箱”复用,相对继承关系而言,其耦合度相对较低,成员对象的变化对新对象的影响不大,可以在新对象中根据实际需要有选择性地调用成员对象的操作;合成复用可以在运行时动态进行,新对象可以动态地引用与成员对象类型相同的其他对象。

      一般而言,如果两个类之间是“Has-A”的关系应使用组合或聚合,如果是“Is-A”关系可使用继承。"Is-A"是严格的分类学意义上的定义,意思是一个类是另一个类的"一种";而"Has-A"则不同,它表示某一个角色具有某一项责任。

 

 

 

名词解释:

 

关联关系:类之间的联系

public class B {
	private A a;
	........
}

public class A{
	........
}

 

 

聚合关系: 成员类是整体类的一部分,即成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在

public class B {
	private A a;

	public B(A a) {
		this.a = a;
	}

	public void setA(A a) {
		this.a = a;
	}
}

public class A{
	........
}

 

 

 

 

组合关系:也是整体与部分的关系,但是整体与部分不可以分开。

       也表示类之间整体和部分的关系,但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在,部分对象与整体对象之间具有同生共死的关系。

public class B {
	private A a;

	public B() {
		a = new A();
	}
}

public class A{
	........
}
 

 下面是粘过来的

设计原则名称

  

使用频率

单一职责原则

(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)

一个软件实体应当尽可能少地与其他实体发生相互作用

★★★☆☆

【作者:刘伟  http://blog.csdn.net/lovelion

 

 

参考书籍:《设计模式之禅》

博客参考: http://my.csdn.net/LoveLion

6
1
分享到:
评论

相关推荐

    程序员必备的七大面向对象设计原则

    下面是七大面向对象设计原则的总结: 一、开闭原则 开闭原则是面向对象设计中最重要的原则之一。它定义为:一个软件实体应当对扩展开放,对修改关闭。也就是说,在设计一个模块的时候,应当使这个模块可以在不被...

    面向对象的设计的原则 电子版

    单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则。 2. 开闭原则(OCP):一个软件实体应当对扩展开放,对修改关闭。开闭原则是面向对象设计的核心原则之一,它告诉我们,在软件设计中,...

    软件体系结构七大设计原则

    软件体系结构七大设计原则是构建高质量软件系统的基础,它们分别是:单一职责原则、开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则和合成聚合原则。这些原则旨在提高软件的可维护性、可扩展性和可...

    61条面向对象设计的经验原则

    ### 61条面向对象设计的经验原则 #### 面向对象设计基本原则 **原则一:** 面向对象设计应该关注于清晰地定义类及其责任。这意味着每个类都应该有明确的目的,并且只负责执行那些与之直接相关的任务。 **原则二:...

    C#面向对象设计的七大原则

    本文将详细介绍C#面向对象设计的七大原则,这些原则是指导我们编写可维护、可扩展的高质量代码的关键。 1. **开闭原则**:开闭原则主张软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不...

    第一章设计模式与七大原则.doc

    设计模式是软件工程中的一种重要思想,它是经验丰富的软件开发者在实践中提炼出来的一套解决方案模板。...在实际开发中,选择合适的设计模式和遵循设计原则,可以帮助我们构建出更加优雅、可扩展的系统。

    单项选择题标准化考试系统设计.doc

    本文档是关于单项选择题标准化考试系统设计的文档,包含了面向对象程序设计(C++)课程大作业设计题目。以下是从该文档中提取的相关知识点: 一、面向对象程序设计(C++)基础知识 * 面向对象程序设计的基本概念:...

    韩顺平_Java设计模式笔记.docx

    通过遵循设计模式,可以降低软件的耦合度,增强内聚性,提高代码的可维护性和可扩展性,同时还能实现更好的重用性、灵活性,使得软件能够适应不断变化的需求。 总之,这门课程全面深入地探讨了Java设计模式及其应用...

    设计模式整理.docx

    这些原则共同构成了面向对象设计的核心指导思想,它们有助于创建出可扩展、可维护、易于理解的高质量软件。在实际开发中,结合这些原则使用设计模式,如工厂模式、单例模式、观察者模式等,能够更好地应对复杂的软件...

    设计模式(用Java描述)详解

    本文将深入探讨七种面向对象的设计原则以及常见的设计模式。 首先,我们来看七种面向对象的设计原则: 1. **单一职责原则 (SRP)**:每个类或模块应专注于一个特定的职责,这有助于提高代码的内聚性和降低耦合度。...

    常用的设计模式

    文档提到的Java设计模式对开发者来说是一套系统的编程思想,它强调的是面向对象的编程理念和接口编程,通过学习设计模式可以加深对面向对象概念的理解,并能够在实际开发中更加得心应手地编写出低耦合、高内聚的代码...

    软件系统分析与设计大作业.doc

    例如,在游戏平台管理系统中,我们需要遵循高内聚、低耦合、抽象、封装等设计原则,以确保系统的可维护性、灵活性和可扩展性。 八、设计模式 设计模式是软件系统分析与设计的重要组成部分。例如,在游戏平台管理...

    《软件架构设计》

    “7Layer”可能指的是七层模型,这是分层架构设计的一种,每一层负责不同的功能,确保了系统组件间的低耦合性和高内聚性。同样,“ProjectProject”和“PCSchemaTier”可能涉及项目管理、PC架构和数据库模式设计。 ...

    设计模式汇总(含思维导图)

    4. 高内聚低耦合原则:提高模块的独立性,降低模块间的耦合度。 5. 单一职责原则:一个类应该仅有一个引起它变化的原因。 6. 里氏替换原则:任何基类可以出现的地方,子类一定可以出现。 7. 依赖倒置原则:高层模块...

    Java学习笔记(必看经典)

    面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将计算机程序设计成由独立的、可重用的、封装良好的组件(即对象)构成,这些组件具有属性和行为。面向对象编程的核心概念包括封装、继承和...

    期末救命版-软件设计与体系结构-清华大学出版社-主编-秦航期末救命版-软件设计与体系结构-清华大学出版社-主编-秦航

    模块化和信息隐藏是提高软件质量的关键,高内聚、低耦合的模块设计能增强软件的可维护性和可扩展性。软件设计过程通常包括需求分析、架构设计、详细设计、编码、测试和维护等阶段。 第五章 不同的软件体系结构风格...

Global site tag (gtag.js) - Google Analytics