面向对象设计_面向对象设计原则 - CSDN
精华内容
参与话题
  • 面向对象设计

    千次阅读 2018-07-16 10:52:39
    面向对象设计 面向对象基本概念 面向对象程序设计(Object-oriented programming即OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。 面向对象编程...

    面向对象设计

    面向对象基本概念

    面向对象程序设计(Object-oriented programmingOOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。

    面向对象编程的两个重要概念是类和对象。

    类:类是变量与作用这些变量的方法集合,事物都具有其自身的属性和方法,通过这些属性和方法可以将不同的物质区分开来。

    对象:对象是类进行实例化后的产物,是一个实体。

    面向对象基本特征

    封装

    封装是面向对象的特征之一,是对象和类概念的主要特性。

    封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的类进行信息隐藏。

    继承

    继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

    • 通过继承创建的新类称为“子类”或“派生类”。
    • 被继承的类称为“基类”、“父类”或“超类”。
    • 继承的过程,就是从一般到特殊的过程。

    继承概念的实现方式有三类:实现继承、接口继承和可视继承。

    • 实现继承:使用基类的属性和方法而无需额外编码的能力;
    • 接口继承:仅使用属性和方法的名称、但是子类必须提供实现的能力;
    • 可视继承:子窗体(类)使用基窗体(类)的外观和实现代码的能力。

    OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

    多态

    所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

    最常见的多态就是将子类传入父类参数中,运行时调用父类方法时通过传入的子类决定具体的内部结构或行为。

    实现多态,有两种方式,覆盖和重载。覆盖和重载的区别在于,覆盖在运行时决定,重载是在编译时决定。并且覆盖和重载的机制不同,例如在 Java 中,重载方法的签名(方法签名:方法名+形参列表)必须不同于原先方法的,但对于覆盖签名必须相同。

    面向对象设计原则

    开闭原则

    开闭原则(Open Close PrincipleOCP)是Java中最基础的设计原则,它可以帮助我们建立一个稳定、灵活的系统。

    定义

    软件中的对象(类、模块、函数等)应该对于扩展是开放的,但是对于修改是封闭的。

    实例分析

    我们假设当前有一个书籍销售的功能模块,程序原本的类图如下:

    面向对象开闭原则1

    此时,因为书店打折活动,书籍价格会产生变化,我们需要修改程序的getPrice()方法,我们可以修改接口IBook,也可以修改其实现类NovelBook,但是这样的话都会在类中产生两个读取价格的方法,顾这两种方法都不是最优的解决办法。如下图所示,我们新建一个OffNovelBook,让其继承NovelBook并重写getPrice方法,新建高层类,通过复写来改变业务逻辑,减少底层代码的修改,减少代码风险。

    面向对象开闭原则2

    我们可以把变化归类为两种类型:

    • 逻辑变化:只变化了一个逻辑,而不涉及到其他模块的变化,可以直接修改原有类中的方法来实现,但这有一个前提条件是所有依赖或关联都按照相同的逻辑处理。
    • 子模块变化:一个模块的变化,会对其他模块产生影响,特别是一个低层次的模块变化必然引起高层模块的变化,因此诸如此类的变化应通过扩展来完成。

    总结

    • 抽象约束 :通过接口或抽象类约束扩展,对扩展进行边界限定 ;参数类型、引用对象尽量使用接口或抽象类,而不是具体的实现类 ;抽象层尽量保持稳定,一旦确定就不要修改 。
    • 元数据(metadata)控制模块行为 :元数据就是用来描述环境和数据的数据。尽量使用元数据来控制程序的行为,减少重复开发 。
    • 封装变化:将相同的变化封装到一个接口或抽象类中,不同的变化应封装在不同的接口或抽象类中,否则即违背了单一职责原则。

    单一职责原则

    单一职责原则(Single Responsibility PrincipleSRP),其核心的思想是: 一个类,最好只做一件事,只有一个引起它变化的原因。

    定义

    单一职责,强调的是职责的分离,在某种程度上对职责的理解,构成了不同类之间耦合关系的设计关键,因此单一职责原则或多或少成为设计过程中一个必须考虑的基础性原则。

    实例分析

    public void addProduct() {
        if (!getCuurentUserPermission.contains("product.add")) {
            //当前用户不具有add权限
            return;
        } 
        //业务逻辑
    }

    从以上代码,我们不难看出,如果该功能对应的权限规则发生了变化 ,那么我们需要对系统中所有诸如此类的类进行修改。这将大大降低程序的稳定性,同时也会大大的提高我们得工作量。

    对于这种情况我们可以新建一个类(权限控制类,比如shiro框架)来做处理。在shrio框架中,可以通过注解的方式去配置权限代码来实现权限控制,同理我们也可自己写一个方法,例如:PermisssionUtils.haveRight(String permissionCode),在调用addProduct之前去判断是否拥有权限,从而使业务逻辑与权限控制两个职责分离。

    PermisssionUtils.haveRight("product.add");
    addProduct();

    总结

    单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为类实现过多的功能点,以保证实体只有一个引起它变化的原因。

    里氏替换原则

    里氏替换原则(Liskov Substitution Principle,即LSP):所有引用父类的地方必须能使用其子类的对象。

    定义

    所有引用父类的地方必须能使用其子类的对象

    在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用父类对象。

    实例分析

    在下文关于依赖倒置原则的实例中:

    public class Client {
        public static void main(String[] args) {
            People jim = new Jim();
            Fruit apple = new Apple();
            Fruit banana = new Banana();
            jim.eat(apple);
            jim.eat(banana);
        }
    }

    我们将Banana赋值给其父类Banana,并且在执行jim.eat(Banana)方法时得到了我们期望的结果。

    总结

    里氏替换原则是实现开闭原则的重要方式之一,由于使用父类对象的地方都可以使用子类对象,因此在程序中尽量使用父类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。通常我们会使用接口或者抽象方法定义基类,然后子类中实现父类的方法,并在运行时通过各种手段进行类型选择调用(比如反射)。

    子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法。根据里氏替换原则,为了保证系统的扩展性,在程序中通常使用父类来进行定义,如果一个方法只存在子类中,在父类中不提供相应的声明,则无法在以父类定义的对象中使用该方法。

    我们在运用里氏替换原则时,尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。里氏替换原则是开闭原则的具体实现手段之一。这也就是我们应该更多的依赖抽象,尽量少的依赖实现细节, 也就是依赖倒置原则。

    依赖倒置原则

    依赖倒置原则(Dependency Inversion PrincipleDIP)

    定义

    • 高层模块不应该依赖低层模块,两者都应该依赖其抽象
    • 抽象不应该依赖细节
    • 细节应该依赖抽象

    抽象:抽象类或接口,两者是不能被实例化的

    细节:抽象具体的实现类,实现接口或继承抽象类所产生的类(可以被实例化的类)

    实例分析

    //具体Jim人类
    public class Jim {
        public void eat(Apple apple){
            System.out.println("Jim eat " + apple.getName());
        }
    }
    //具体苹果类
    public class Apple {
        public String getName(){
            return "apple";
        }
    }
    public class Client {
        public static void main(String[] args) {
            Jim jim = new Jim();
            Apple apple = new Apple();
            jim.eat(apple);
        }
    }

    从上述代码,我们不难看出,该程序所表示的人吃苹果。此时我们如果要加一条人吃香蕉,只能先定义一个Banana类,然后在修改Jim类,在其中加一个吃香蕉的方法。加一种尚且如此,那么加n种呢?并且修改Jim类的操作会大大减少系统的稳健性,顾应根据依赖倒置原则对源码进行修改,修改如下:

    //人接口
    public interface People {
        public void eat(Fruit fruit);//人都有吃的方法,不然都饿死了
    }
    //水果接口
    public interface Fruit {
        public String getName();//水果都是有名字的
    }
    //具体Jim人类
    public class Jim implements People{
        public void eat(Fruit fruit){
            System.out.println("Jim eat " + fruit.getName());
        }
    }
    //具体苹果类
    public class Apple implements Fruit{
        public String getName(){
            return "apple";
        }
    }
    //具体香蕉类
    public class Banana implements Fruit{
        public String getName(){
            return "banana";
        }
    }
    public class Client {
        public static void main(String[] args) {
            People jim = new Jim();
            Fruit apple = new Apple();
            Fruit banana = new Banana();
            jim.eat(apple);
            jim.eat(banana);
        }
    }

    总结

    总而言之,依赖倒置原则的核心就是面向接口编程,对于一些底层类都提取抽象类和公共接口,顶层类依赖抽象类或接口而不直接依赖具体实现。

    依赖倒置原则的本质是通过抽象类或接口使各个类或模块的实现彼此独立,不相互影响,实现模块之间的松耦合。

    在多人协作时,我们还可以遵循依赖倒置原则去设计程序,提取抽象,使得各模块相对独立,提升并行开发效率,提高开发速度。

    接口隔离原则

    接口隔离原则(Interface Segregation Principle, 即ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

    定义

    • 客户端不应该依赖它不需要的接口。

    • 类间的依赖关系应该建立在最小的接口上。

    • 接口隔离原则将非常庞大、臃肿的接口拆分成为更小的和更具体的接口,这样客户将会只知道他们感兴趣的方法。

    实例分析

    例如:客户端的用户需要登录、登出、修改密码等操作,而后台的管理员则可以修改用户资料、删除用户等操作。

    public interface UserService{
        public void login();
        public void logout();
        public void changePassword();
    }
    public interface AdminUserService extends UserService {
        public void updateUser(User user);
        public void deleteUser(User user);
    }

    总结

    接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。

    接口隔离原则与前面的单一职责原则相辅相成。但单一职责原则并不保证客户程序只知道必要的信息,甚至在有些情况下接口隔离原则与单一职责原则会出现一定的冲突,设计时我们要根据用户界面,性能等因素决策.。

    运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。

    迪米特法则

    迪米特法则(Law of Demeter, 即LOD):一个软件实体应当尽可能少地与其他实体发生相互作用。

    迪米特法则又称为最少知识原则(LeastKnowledge Principle,即LKP)

    定义

    不要和“陌生人”说话、只与你的直接朋友通信

    在迪米特法则中,对于一个对象,其朋友包括以下几类:

    • 当前对象本身(this)
    • 以参数形式传入到当前对象方法中的对象
    • 当前对象的成员对象
    • 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友
    • 当前对象所创建的对象

    任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要与“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响 。

    实例分析

    例如:现在用户像好友发送消息,用户可以对单个好友发送消息,也可以发送群消息。

    迪米特恩法则

    从上图不难看出,我们专门引入了一个MessageService用与控制消息转发,同时降低UserService与各系统之间的耦合度。当需要新增功能时,只需修改MessageSerice即可。

    总结

    迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度

    在运用迪米特恩法则时应注意以下几点:

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

    组合/聚合复用原则

    组合/聚合复用原则(Composite/Aggregate Reuse PrincipleCARP

    定义

    组合和聚合都是对象建模中关联(Association)关系的一种.聚合表示整体与部分的关系,表示“含有”,整体由部分组合而成,部分可以脱离整体作为一个独立的个体存在。组合则是一种更强的聚合,部分组成整体,而且不可分割,部分不能脱离整体而单独存在。在合成关系中,部分和整体的生命周期一样,组合的新的对象完全支配其组成部分,包括他们的创建和销毁。一个合成关系中成分对象是不能与另外一个合成关系共享。

    实例分析

    组合/聚合和继承是实现复用的两个基本途径。合成复用原则是指尽量使用合成/聚合,而不是使用继承。 只有当以下的条件全部被满足时,才应当使用继承关系。

    • 继承复用破坏包装,它把父类的实现细节直接暴露给了子类,这违背了信息隐藏的原则。
    • 如果父类发生了改变,那么子类也要发生相应的改变,这就直接导致了类与类之间的高耦合,不利于类的扩展、复用、维护等,也带来了系统僵硬和脆弱的设计。
    • 合成和聚合的时候新对象和已有对象的交互往往是通过接口或者抽象类进行的,就可以很好的避免上面的不足,而且这也可以让每一个新的类专注于实现自己的任务,符合单一职责原则。

    判断方法:

    1.使用“Has-A”和“Is-A”来判断:

    “Has-A”:代表的是 对象和它的成员的从属关系。同一种类的对象,通过它们的属性的不同值来区别。比如一个人可以是医生、警察、教师等。此时可使用继承关系

    “Is-A”:代表的是类之间的继承关系,比如一个人可以是男人、女人。此时应使用组合/聚合

    2.使用里氏替换原则来判断

    里氏代换原则是继承复用的基础。

    总结

    继承的缺点:

    • 继承复用破坏数据封装性,将基类的实现细节全部暴露给了派生类,基类的内部细节常常对派生类是透明的,白箱复用。虽然简单,但不安全,不能在程序的运行过程中随便改变。
    • 基类的实现发生了改变,派生类的实现也不得不改变。
    • 从基类继承而来的派生类是静态的,不可能在运行时间内发生改变,因此没有足够的灵活性。

    组合/聚合优点:

    • 新对象存取组成对象的唯一方法是通过组成对象getter/setter方法。
    • 组合复用是黑箱复用,因为组成对象的内部细节是新对象所看不见的。
    • 组合复用所需要的依赖较少。
    • 每一个新的类可以将焦点集中到一个任务上。
    • 组合复用可以在运行时间动态进行,新对象可以动态的引用与成分对象类型相同的对象。

    组合/聚合缺点:组合复用建造的系统会有较多的对象需要管理。

    展开全文
  • 面向对象设计六大原则

    千次阅读 2019-04-15 16:33:11
    1)单一职责原则,一个合理的类,应该仅有一个引起它变化的原因,即单一职责,就是设计的这个类功能应该只有一个;  优点:消除耦合,减小因需求变化引起代码僵化。 2) 开-闭原则,讲的是设计要对扩展有好的支持,而...

    6大原则如下:

    1)单一职责原则,一个合理的类,应该仅有一个引起它变化的原因,即单一职责,就是设计的这个类功能应该只有一个;

      优点:消除耦合,减小因需求变化引起代码僵化。

    2) 开-闭原则,讲的是设计要对扩展有好的支持,而对修改要严格限制。即对扩展开放,对修改封闭。

      优点:降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无须为原有模块进行重新测试。

    3) 里氏代换原则,很严格的原则,规则是“子类必须能够替换基类,否则不应当设计为其子类。”也就是说,一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化。

      优点:可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉。

    4) 依赖倒换原则,“设计要依赖于抽象而不是具体化”。换句话说就是设计的时候我们要用抽象来思考,而不是一上来就开始划分我需要哪些哪些类,因为这些是具体。

    “High level modules should not depend upon low level modules, both should depend upon abstractions. Abstractions should not depend upon details, details should depend upon abstractions.”

    高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

    另一种表述为: 要针对接口编程,不要针对实现编程。即“Program to an interface, not an implementation.”

      优点:人的思维本身实际上就是很抽象的,我们分析问题的时候不是一下子就考虑到细节,而是很抽象的将整个问题都构思出来,所以面向抽象设计是符合人的思维的。另外这个原则会很好的支持(开闭原则)OCP,面向抽象的设计使我们能够不必太多依赖于实现,这样扩展就成为了可能,这个原则也是另一篇文章《Design by Contract》的基石。

    5) 接口隔离原则,“将大的接口打散成多个小接口”,让系统解耦,从而容易重构,更改和重新部署。

      优点:会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里。

    6) 迪米特法则或最少知识原则,这个原则首次在Demeter系统中得到正式运用,所以定义为迪米特法则。它讲的是“一个对象应当尽可能少的去了解其他对象”。

      优点:消除耦合。

    展开全文
  • 面向对象设计原则

    万次阅读 2018-10-08 10:46:05
    面向对象的软件设计中,有23种经典的设计模式,是一套前人代码设计经验的总结,如果把设计模式比作武功招式,那么设计原则就好比是内功心法。常用的设计原则有七个,下文将具体介绍。 七种设计原则简单归纳如下 ...

    在面向对象的软件设计中,只有尽量降低各个模块之间的耦合度,才能提高代码的复用率,系统的可维护性、可扩展性才能提高。面向对象的软件设计中,有23种经典的设计模式,是一套前人代码设计经验的总结,如果把设计模式比作武功招式,那么设计原则就好比是内功心法。常用的设计原则有七个,下文将具体介绍。

    七种设计原则简单归纳如下

    • 单一职责原则:专注降低类的复杂度,实现类要职责单一;
    • 开放关闭原则:所有面向对象原则的核心,设计要对扩展开发,对修改关闭;
    • 里式替换原则:实现开放关闭原则的重要方式之一,设计不要破坏继承关系;
    • 依赖倒置原则:系统抽象化的具体实现,要求面向接口编程,是面向对象设计的主要实现机制之一;
    • 接口隔离原则:要求接口的方法尽量少,接口尽量细化;
    • 迪米特法则:降低系统的耦合度,使一个模块的修改尽量少的影响其他模块,扩展会相对容易;
    • 组合复用原则:在软件设计中,尽量使用组合/聚合而不是继承达到代码复用的目的。

    那么如何去遵守这七个原则?设计原则的遵守并不是是和否的问题,而是度的问题。任何事物过犹不及,设计原则也是一样,制定这七个原则并不是一味的要求我们去遵守他们,而是根据实际情况灵活运用。

    下图中的每一条维度代表一项原则,依据遵守程度在维度上画一个点,如果对这项原则遵守的合理的话,这个点会落在环内,如果遵守的少会落在小圆圈里面,过度遵守会落在大圆圈外面,一个良好的设计体现在图中,应该是七个点都落在环中的七边形。
    在这里插入图片描述

    如下图,图1(从左到右)属于良好设计,七个设计原则遵守程度都在合理范围内;图2虽然有些不足,但也可以接受;图3和图4,一个几乎不遵守,一个遵守过度,这两种设计模式都需要进行重构。
    在这里插入图片描述

    单一职责原则

    一个类只负责一个功能领域中的相应职责。就一个类而言,应该只有一个引起它变化的原因。
    不同的类具备不同的职责,各司其职,有以下优点。

    • 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
    • 类的可读性高,进而可以提高系统的可维护性;
    • 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。

    单一职责原则是最简单但又最难运用的原则,难点在于职责和粒度划分。一个类往往具有多重职责,而发现类的多重职、职责粒度拆分的大小需要要设计人员具有较强的分析设计能力和相关实践经验。

    开放关闭原则

    一个软件实体(软件实体可以指一个软件模块、一个由多个类组成的局部结构、一个独立的类甚至一个函数)应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

    软件系统的需求变化是不可避免的,当我们实现新需求时,需要尽量保证系统的稳定性和扩展性。符合开放关闭原则的系统,可以很容易地扩展,且扩展时无须修改现有代码,使得系统的扩展性和稳定性有很大提高。随着时间的推移,软件规模越来越大,维护成本越来越高,设计满足开放关闭原则的软件系统也变得越来越重要。

    系统的抽象化设计,是开放关闭原则的关键。可以通过接口、抽象类定义系统的抽象层,通过实现类进行扩展,增加新功能只需增加新的实现类,而无需修改抽象层,从而实现在不修改已有代码的情况下实现系统扩展。

    里氏替换原则

    里氏代换原则由2008年图灵奖得主、美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出。其严格表述为“如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1代换o2时,程序P的行为没有变化,那么类型S是类型T的子类型。”通俗的讲即所有引用基类(父类)的地方必须能透明地使用其子类的对象。

    里氏替换原则是实现开放关闭原则的的重要实现手段之一,由于使用基类对象的地方都可以使用子类对象,因此尽量使用基类类型定义对象,而在运行时再确定其子类类型,用子类对象来替换父类对象。

    依赖倒置原则

    抽象不应该依赖于细节,细节应当依赖于抽象。依赖倒转原则要求我们要针对接口编程,不针对具体实现编程。在程序代码中传递参数时或在关联关系中,尽量引用高层的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。这样一来,如果系统行为发生变化,只需对抽象层进行扩展,而不必修改系统现有的业务逻辑,从而满足开放关闭原则的要求。时下各种开发框架提供的依赖注入功能都很好的应用了此原则。

    在大多数情况下,开放关闭原则、里氏代换原则和依赖倒置原则这三个设计原则会同时出现,开放关闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同而已。

    接口隔离原则

    使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。接口隔离原则有两层含义:(1)客户需要什么样的接口,就提供什么样的接口,不需要的就删除掉;(2)类之间的依赖关系应建立在最小接口上,也就是说接口要尽量的细化,同时接口中的方法应该尽量少,职责要尽可能单一。

    当一个接口太大时,我们需要将它分割成多个更小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事。

    在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护;接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。一般而言,接口中仅包含为某一类用户定制的方法即可,不应该强迫客户依赖于那些它们不用的方法。

    迪米特法则

    迪米特法则又叫最小知识原则,一个软件实体应当尽可能少地与其他实体发生相互作用。迪米特法则是对软件系统中实体之间通信的限制,对实体之间通信的宽度和深度提出了要求。迪米特法则要求当修改系统的某一个模块时,要尽量少地影响其他模块,从而使类与类之间保持松散的耦合关系,使系统扩展相对容易。
    迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类:

    • 当前对象本身(this);
    • 以参数形式传入到当前对象方法中的对象;
    • 当前对象的成员对象;
    • 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;
    • 当前对象所创建的对象。

    任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要与“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响。

    迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

    在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

    组合复用原则

    组合复用原则也叫合成/聚合复用原则(CARP),就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些已有对象委派任务,从而达到复用已有功能的目的。简单的说是,尽量使用对象的组合/聚合(has-a),而不是继承(is-a)来达到复用的目的。

    组合/聚合和继承是实现代码复用的两种基本途径,在设计过程中尽量使用组合/聚合,而不是继承。因为继承使得基类与子类有较强的耦合性,通常情况下基类的内部细节对子类来说是可见的,这样基类的实现细节会暴露给子类,破坏了系统的封装性。

    展开全文
  • 面向对象设计步骤

    千次阅读 2015-08-09 13:56:02
    面向对象设计步骤 1、 先根据需求找出对象 2、 抽象每一个对象为类 3、 找出各对象之间的关系,使用组合、继承、分类、扩展等描述这些关系 4、 找出每个对象实体要做的事,写对象方法 5、  找出...

    面向对象的设计步骤


    1、
    先根据需求找出对象
    2、
    抽象每一个对象为类
    3、
    找出各对象之间的关系,使用组合、继承、分类、扩展等描述这些关系
    4、
    找出每个对象实体要做的事,写对象方法
    5、
     找出每个类在不需要有对象实体的情况下要做的事,写类方法

    展开全文
  • 什么是面向对象程序设计

    万次阅读 2019-09-23 13:23:40
    1.面向对象和面向过程区别→2.什么是对象→3.什么是消息→4.什么是封装→5.什么是多态→6.面向对象的优点: 本文介绍 C++基础概念和知识。如果您想看其他语言(如 java)的语法,本文不涉及。 1.面向对象和面向...
  • 面向对象的分析与设计

    万次阅读 2019-12-09 16:17:19
    一、传统开发方法中存在的问题 在二十世纪六十年代以前,软件系统都是较小且相对简单的;...当时系统设计时常用的方法有功能分解法和数据流法。 1、功能分解法(function decomposition) 以系...
  • 面向对象设计原则(一)

    千次阅读 2017-11-22 11:08:48
    同时面向对象设计原则也是用于评价一个设计模式的使用效果的重要指标之一,在设计模式的学习中,经常会看到诸如“XXX模式符合XXX原则”、“XXX模式违反了XXX原则”这样的语句,以此来评判设计模式的不足。...
  • 面向对象设计的七大设计原则详解

    万次阅读 多人点赞 2019-08-06 16:37:18
    面向对象的七大设计原则 文章目录面向对象的七大设计原则简述七大原则之间的关系一、开闭原则(The Open-Closed Principle ,OCP)概念理解系统设计需要遵循开闭原则的原因开闭原则的实现方法一个符合开闭原则的...
  • 软件工程——面向对象设计

    千次阅读 多人点赞 2013-12-07 14:39:16
    说到面向对象我们都很熟悉,刚刚结束的vb... 面向对象设计可以看做是一种在程序中包含各种独立而又相互调用的对象的思想,这与传统的思想不同。传统的思想更侧重于把程序看作一系列函数的集合,或者是直接对电脑下达
  • =======================...面向对象设计原则(一共八种) C++设计模式(一共23种) ================================================================== 目录 面向对象设计原则(一共八种) C++设计模式(...
  • 面向对象设计原则概述

    万次阅读 多人点赞 2013-12-22 22:15:12
    对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。在面向对象设计中,可维护...
  • 设计模式需要遵循基本的软件设计原则。...面向对象设计的原则是支持可维护性复用,一方面需要实现设计方案或代码的复用,另一方面要保证系统易于扩展和修改,具有良好的可维护性。面向对象设计原则蕴含在各个设计...
  • 面向对象设计原则之开闭原则

    万次阅读 多人点赞 2012-05-06 21:39:33
    开闭原则是面向对象的可复用设计的第一块基石,它是最重要的面向对象设计原则。开闭原则由Bertrand Meyer于1988年提出,其定义如下: 开闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开放...
  • 面向对象设计与分析

    千次阅读 2012-08-04 18:59:28
    面向对象设计与分析 2009-04-18 10:30 96人阅读 评论(0) 收藏 举报 面向对象  面向对象(Object Oriented,OO)是当前计算机界关心的重点,它是90年代软件开发方法的主流。面向对象的概念和应用已超越了...
  • 谈谈8年C++面向对象设计的经验体会

    千次阅读 2016-07-23 14:47:31
    软件工程中的时髦术语“面向对象分析”和“面向对象设计”,通常是针对“需求分析”和“系统设计”环节的。“面向对象”有几大学派,就象如来佛、上帝和真主用各自的方式定义了这个世界,并留下一堆经书来解释这个
  • 面向对象分析和面向对象设计的区别
  • 结构化设计和面向对象设计

    千次阅读 2010-01-31 14:36:00
    再探结构化设计和面向对象设计方法http://www.csai.cn 作者:fasiondog 来源:CSDN 2006年9月8日 进入社区 结构化设计历来备受责备的就是需求和设计之间的鸿沟,以前不是很理解这个鸿沟的原因。现在再看,在结构...
  • (小白)面向对象设计中接口的作用

    千次阅读 2017-11-25 10:23:46
    最近学了一门神课《系统分析与设计》,学习了...看了很多例子之后,似乎对面向对象设计中的“接口”有了一点点体会,赶紧记录下来。 我目前体会到的接口的作用主要有以下两点: (1)接口作为约束与规范 (2)优化设计
  • 在学习面向对象设计对象关系时,依赖、关联、聚合和组合这四种关系之间区别比较容易混淆。特别是后三种,仅仅是在语义上有所区别,所谓语义就是指上下文环境、特定情景等。他们在编程语言中的体现却是基本相同的,...
  • 面向对象设计和面向组件设计有哪些不同之处?面向对象和面向组件设计之间的不同之处在于着眼的粒度不一样,面向对象关注类与类之间的关系,面向组件着眼于可以独立工作的可替换的代码模块,并且使用的时候无需直销其...
1 2 3 4 5 ... 20
收藏数 566,967
精华内容 226,786
关键字:

面向对象设计