`

浅析OOP原则

阅读更多

前言:    

      学习java编程已经有相当长的一段时间了,可以说对面向对象语言编程已经是有了相当深刻的理解了。每一个程序员在编写代码的时候不仅要能够用一门语言来实现我们的想要的东西,而且还要有规范我们所做的工作的一套原则。我想不仅是编程,做每一件事情包括做人都要有自己的原则性。说到java编程,OOP原则就要上场了。。。

      OOP: Object Oriented Programming,面向对象的程序设计。所谓“对象”就是一个或一组数据以及处理这些数据的方法和过程的集合。面向对象的程序设计完全不同于传统的面向过程程序设计,它大大地降低了软件开发的难度,使编程就像搭积木一样简单,是当今电脑编程的一股势不可挡的潮流。

  OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。OOP 主要有以下的概念和组件:

      组件 - 数据和功能一起在运行着的计算机程序中形成的单元,组件在 OOP 计算机程序中是模块和结构化的基础。

  抽象性 - 程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。

  封装 - 也叫做信息封装:确保组件不会以不可预期的方式改变其它组件的内部状态;只有在那些提供了内部状态改变方法的组件中,才可以访问其内部状态。每类组件都提供了一个与其它组件联系的接口,并规定了其它组件进行调用的方法。

  多态性 - 组件的引用和类集会涉及到其它许多不同类型的组件,而且引用组件所产生的结果得依据实际调用的类型。

  继承性 - 允许在现存的组件基础上创建子类组件,这统一并增强了多态性和封装性。典型地来说就是用类来对组件进行分组,而且还可以定义新类为现存的类的扩展,这样就可以将类组织成树形或网状结构,这体现了动作的通用性。

 

 

      国际上一般认为OPP一共有七大原则,分别是以下七大原则:

一  OCP(Open-Closed Principle) 开放-封闭原则
    软件实体应该扩展开放、修改封闭:
    1. “对于扩展是开放的” (Open for extension)。这意味着模块的行为是可以扩展的,当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为,换句话说,我们可以改变模块的功能。
    2. “对于更改是封闭的” (Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码,模块的二进制可执行版本,无论是可链接的库、DLL或JAVA 的.jar文件,都无需改动。
    实现:合理划分构件,一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里;一种可变性不应当和另一个可变性混合在一起。

二 DIP(Dependency-Inversion Principles)依赖倒置原则
    第1点:高层模块不依赖底层模块,两者都依赖抽象。
    第2点:抽象不应该依赖于细节,细节应该依赖于抽象。
    每个较高层次都为它所需要的服务声明一个抽象接口,较低的层次实现这些抽象接口,每个高层类都通过该抽象接口使用下一层的服务,接口属于高层,低层要实现高层的接口,因此现在是低层依赖于高层是依赖关系倒置和接口所有权的倒置。
    实现:应该通过抽象耦合的方式,使具体类最大可能的仅和其抽象类(接口)发生耦合;程式在需要引用一个对象时,应当尽可能的使用抽象类型作为变量的静态类型,这就是针对接口编程的含义。

LSP(Liskov Substitution Principle) 替换原则

    继承思想的基础。“只有当衍生类能够替换掉基类,软件单位的功能不会受到影响时,基类才真正被复用,而衍生类也才能够在基类的基础上增加新的行为。

四 ISP(Interface Insolation Principle)接口隔离原则
    接口功能单一,避免接口污染。
    一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染----角色隔离原则。
    将接口理解成为侠义的java接口,这样一来,接口隔离原则讲的就是为同一个角色提供宽、窄不同的接口,以对付不同的客户端。这种办法在服务行业中叫做定制服务---定制服务。
       实现:一个类对另外一个类的依赖性应当是建立在最小的接口上的。使用多个专门的接口比使用单一的总接口要好。
    (动机:当我们设计应用程序的时候,如果一个模块包含多个子模块,那么我们应该小心对该模块做出抽象。设想该模块由一个类实现,我们可以把系统抽象成一个接口。但 是当我们想要添加一个新的模块扩展程序时,如果要添加的模块只包含原系统中的一些子模块,那么就会强迫我们实现接口中的所有方法,并且还要编写一些哑方 法。这样的接口被称为胖接口或者叫被污染的接口,使用这样的接口将会给系统引入一些不正确的行为。)

五 SRP(Single Resposibility Principle) 单一职责原则
    就一个类而言,应该仅有一个引起他变化的原因。 假如一个类的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会抑止这个类完成其他职责的能力。
    单一职责原则的好处:
    第一、有助于我们分析和编码的思路的清晰。(当你的代码里有了三层或以上的if语句或for语句的嵌套的时候,你不要跟我说,你已经把问题分析得很清楚了。多层嵌套的if或for语句只能说明你还没有把问题分析清楚。)
    第二、使我们的编码、测试和维护变得简单。
    第三、将一个个复杂的问题简单化以后,易于代码的重用。(当你的代码的多个功能搅和在一起的时候,你是没办法考虑代码的重用的,因为你的每一处代码都有不同。)
    第四、易于系统的扩展

 六 LoD (Law of Demeter)迪米特法则
     即最少知识原则。一个对象应当对其他对象有尽可能少的了解。只和最直接的类交互,对第三方可以通过转达交互,从而减少对象间的耦合性。

 七 CARP(Composite/Aggregate Reuse Principle)合成/聚合复用原则
    就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。简而言之就是:要尽量使用合成/聚合,尽量不要使用继承。
    聚合:用来表示“拥有”关系或者整体和部分的关系。
    合成:用来表示一种强得多的“拥有”关系。在一个合成里,部分和整体的生命周期是一样的。一个合成的新对象完全拥有对其组成部分的支配权,包括它们的创建和泯灭等。 
     当然想要很深刻的理解OOP原则光是看点简介是远远不够的,在这里我就拿其中的一个原则 LSP(Liskov Substitution Principle) 替换原则通过举例稍微深入分析一下。
       对于依赖倒置原则,说的是父类不能依赖子类,它们都要依赖抽象类。这种依赖是我们实现代码扩展和运行期内绑定(多态)的基础。因为一旦类的使用者依赖某个具体的类,那么对该依赖的扩展就无从谈起;而依赖某个抽象类,则只要实现了该抽象类的子类,都可以被类的使用者使用,从而实现了系统的扩展。

    但是,光有依赖倒置原则,并不一定就使我们的代码真正具有良好的扩展性和运行期内绑定。请看下面的代码 

public class Animal
{
    private string name;
    public Animal(string name)
    {
        this.name = name;
    }
    public void Description()
    {
        Console.WriteLine("This is a(an) " + name);
    }
}

下面是它的子类猫类:

 

 

 

public class Cat : Animal
{
    public Cat(string name)
    {
        
    }
    public void Mew()
    {
        Console.WriteLine("The cat is saying like 'mew'");
    }
}

 下面是它的子类狗类:

public class Dog : Animal
{
    public Dog(string name)
    {
 
    }
    public void Bark()
    {
        Console.WriteLine("The dog is saying like 'bark'");
    }
}

 最后,我们来看客户端的调用:

public void DecriptionTheAnimal(Animal animal)
{
    if (typeof(animal) is Cat)
    {
        Cat cat = (Cat)animal;
        Cat.Decription();
        Cat.Mew();
    }
    else if (typeof(animal) is Dog)
    {
        Dog dog = (Dog)animal;
        Dog.Decription();
        Dog.Bark();
    }
}

 通过上面的代码,我们可以看到虽然客户端的依赖是对抽象的依赖,但依然这个设计的扩展性不好,运行期绑定没有实现。phpma开源
是什么原因呢?其实就是因为不满足里氏替换原则,子类如CatMew()方法父类根本没有,Dog类有Bark()方法父类也没有,两个子类都不能替换父类。这样导致了系统的扩展性不好和没有实现运行期内绑定。
现在看来,一个系统或子系统要拥有良好的扩展性和实现运行期内绑定,有两个必要条件:第一是依赖倒置原则;第二是里氏替换原则。这两个原则缺一不可。
 
我们知道,在我们的大多数的模式中,我们都有一个共同的接口,然后子类和扩展类都去实现该接口。
下面是一段原始代码:

if(action.Equals(“add”))
{
  //do add action
}
else if(action.Equals(“view”))
{
  //do view action
}
else if(action.Equals(“delete”))
{
  //do delete action
}
else if(action.Equals(“modify”))
{
  //do modify action
}

 我们首先想到的是把这些动作分离出来,就可能写出如下的代码:

 

public class AddAction
{
    public void add()
    {
        //do add action
    }
}
public class ViewAction
{
    public void view()
    {
        //do view action
    }
}
public class deleteAction
{
    public void delete()
    {
        //do delete action
    }
}
public class ModifyAction
{
    public void modify()
    {
        //do modify action
    }
}

 我们可以看到,这样代码将各个行为独立出来,满足了单一职责原则,但这远远不够,因为它不满足依赖颠倒原则和里氏替换原则。phpma开源
下面我们来看看命令模式对该问题的解决方法:

public interface Action
{
    public void doAction();
}
//然后是各个实现:
public class AddAction : Action
{
    public void doAction()
    {
        //do add action
    }
}
public class ViewAction : Action
{
    public void doAction()
    {
        //do view action
    }
}
public class deleteAction : Action
{
    public void doAction()
    {
        //do delete action
    }
}
public class ModifyAction : Action
{
    public void doAction()
    {
        //do modify action
    }
}

 

p这样,客户端的调用大概如下:

public void execute(Action action)
{
    action.doAction();
}

 看,上面的客户端代码再也没有出现过typeof这样的语句,扩展性良好,也有了运行期内绑定的优点。

 

 

 

 

 

 

 

 

 

 

 

2
2
分享到:
评论
1 楼 一碗三餐 2012-04-26  

相关推荐

    OOP(面向对象编程)四个基本原则

    在OOP中,有四个基本原则,它们是设计高质量、可维护软件的基石。这四个原则分别是:开放封闭原则(Open-Closed Principle,OCP)、依赖倒置原则(Dependency Inversion Principle,DIP)、接口分离原则(Interface ...

    OOP设计原则

    **OOP设计原则详解** 面向对象编程(Object-Oriented Programming,简称OOP)是一种流行的编程范式,它强调将数据和操作数据的方法封装在一起,形成独立的对象。OOP设计原则是指导我们如何构建可维护、可扩展和可...

    OOP三大原则

    在OOP中,有三大核心原则,它们分别是单一职责原则(Single Responsibility Principle, SRP)、开放封闭原则(Open-Closed Principle, OCP)和里氏替换原则(Liskov Substitution Principle, LSP)。这些原则是指导...

    OOP的基本设计原则1

    面向对象编程(OOP)是现代软件开发中的基础,遵循一系列设计原则可以帮助我们构建更加稳定、可维护的系统。SOLID原则是OOP设计中最重要的五个原则,它们分别是: 1. 开闭原则(Open-Closed Principle,OCP):一个...

    php5 oop编程书

    面向对象编程是现代软件开发中的核心概念,它通过类和对象的概念,提高了代码的重用性和可...通过学习这本书,你将掌握如何利用OOP原则和设计模式来构建高效、可扩展的PHP应用程序,从而提升你的编程技能和职业发展。

    新闻快客(纯OOP编写)

    通过分析这些源代码,学习者可以深入理解如何在实际项目中运用OOP原则,从而提升自己的编程技能。 总的来说,【新闻快客】是一个理想的案例,可以帮助学习者掌握C#语言的OOP特性,以及如何运用这些特性来构建实用的...

    oop实践

    在实际的软件开发中,OOP是解决复杂问题的有效工具,通过封装、继承和多态等核心原则,可以构建出易于理解和管理的代码结构。 **封装** 是OOP的基础,它将数据和操作数据的方法捆绑在一起,形成一个独立的实体——...

    android架构-复习基本OOP知识d

    本主题"android架构-复习基本OOP知识d"旨在帮助开发者深入理解并熟练运用OOP原则,以便在实际的Android开发工作中实现高效、灵活的代码设计。 面向对象编程有四大基本原则:封装、继承、多态和抽象。这些概念构成了...

    清华大学oop第一讲

    项目设计与实现将考验学生运用OOP原则的能力,而期末报告则要求学生总结学习成果、分享编程技巧,并提出对课程的建议。此外,课堂参与和助教辅导也有助于获取额外加分。 总的来说,这门课程不仅教授OOP的基本概念,...

    OOP.zip_oop

    封装是OOP的基本原则之一,它隐藏了对象的内部细节,只对外提供公共接口来访问和修改数据。在Java中,我们通过访问修饰符(如public、private、protected)来实现封装,确保数据安全,防止不合理的外部访问。 继承...

    工业自动化 TwinCAT3 OOP编程进阶例程

    这些例子将帮助学习者了解如何在实际项目中应用OOP原则来解决自动化问题。 在深入研究之前,你需要对以下概念有一定的了解: 1. 类与对象:类是对象的模板,定义了对象的属性和行为。对象是类的实例,具有特定的...

    oop(面向对象程序设计)考试题

    封装是OOP的首要原则,它将数据和操作数据的方法绑定在一起,隐藏内部实现细节,仅对外提供接口进行交互。这有助于保护数据安全,防止非法访问和修改,同时也提高了代码的可维护性。 继承是另一种关键特性,允许一...

    Java23种设计模式&OOP5;种设计原则

    Java23种设计模式和OOP5种设计原则,祝大家学习愉快。

    编程范式与OOP思想

    编程范式是指导计算机编程语言设计和编程实践的一套原则和理念。它定义了程序设计的骨架和方法论,对程序的结构和编写方式产生深远的影响。在多种编程范式中,面向对象编程(Object-Oriented Programming,OOP)是一...

    绝对经典 用C实现OOP

    《绝对经典:用C实现OOP》是一本深入探讨如何在C语言中模拟面向对象编程(Object-Oriented...通过学习,你可以了解到如何在没有内置OOP支持的语言中实现OOP的设计模式,这对提升编程技能和理解软件设计原则非常有帮助。

    C++(OOP)教材

    C++基于C语言并扩展了其功能,引入了面向对象编程(OOP)的概念,使得程序设计更加贴近实际问题的解决方式。 面向对象程序设计(OOP)的基本思想是将程序设计中的数据和操作数据的方法结合在一起,形成对象。这种...

    oop.rar_oop币

    在IT行业中,面向对象编程(Object-Oriented Programming,简称OOP)是一种广泛使用的编程范式,它将现实世界中的实体抽象为类,...通过深入理解OOP原则并结合业务需求,我们可以创建出一个既实用又易于扩展的系统。

    JavaOOP.xmind

    java oop,适合小白。

    javascript oop模式讲解

    JavaScript OOP(面向对象编程)模式是编程领域中一种重要的设计思想,它允许开发者通过类和对象来组织和管理代码,提高代码的可重用性和可维护性。在这个讲解中,我们将深入探讨JavaScript中的OOP模式,特别是如何...

    OOP设计的一套比较好的架构

    5. SOLID原则:SOLID是面向对象设计的五个基本原则的缩写,包括单一职责原则(Single Responsibility Principle)、开闭原则(Open-Closed Principle)、里氏替换原则(Liskov Substitution Principle)、接口隔离...

Global site tag (gtag.js) - Google Analytics