面向对象基础:OO的五大原则是指SRP、OCP、LSP、DIP、ISP

140 篇文章 0 订阅
订阅专栏
OO的五大原则是指SRP、OCP、LSP、DIP、ISP。

1. SRP(Single Responsibility Principle单一职责原则) 
单一职责很容易理解,也很容易实现。所谓单一职责,就是一个设计元素只做一件事。什么是“只做一件事”?简单说就是少管闲事。现实中就是如此,如果要你专心做一件事情,任何人都有信心可以做得很出色。 

一、定义。

SRP(Single Responsibility Principle):单一职责的原则:一个类应该只有一个发生变化的原因。

每一个职责都是变化的轴线。当需求变化时,该变化会反应为类的职责变化。如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个。

如果一个类承担的职责过多,就等于把这些职责耦合在了一起。一个职责的变化可能会消弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。

如下图的设计。Rectangle类具有两个方法,一个方法把矩形绘制在屏幕上,另一个方法计算矩形的面积。

1

有两个不同的应用程序使用Rectangle类,一个应用程序是有关计算几何学方面的,利用Rectangle类计算几何形状,但不会在屏幕上绘制矩形。另外一个应用程序实质上是有关图形绘制方面的,它可能也会进行一些计算几何学方面的工作,但是他肯定会在屏幕上绘制矩形。

这个设计违反了单一职责的原则(SRP)。Rectangle类具有两个职责。

第一:提供了一个矩形几何形状的数学模型;

第二:把矩形在一个图形用户界面上绘制出来。

导致的问题:

首先,我们必须在计算几何应用程序中包含进GUI代码。在.NET中,就必须要把GUI组建和计算几何应用一起构建、部署。

其次,如果GraphicalApplication的改变由于一些原因导致了Rectangle的改变,那么这个改变会迫使我们重新构建、测试以及部署ComputationalGeometryApplication。如果忘记了这样做,ComputationalGeometryApplication可能会有不可预测的问题。

一个较好的设计是把这两个职责分离到下图中所示的两个完全不同的类中。

2

二、定义职责

在SRP中,我们把职责定义为变化的原因。如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。

如下代码中Modem的接口,大都数人都会认为这个接口看起来非常合理。该接口所声明的4个方法确实是调制解调器所具有的功能。

?
1
2
3
4
5
6
7
public interface IModem
{
void Dial( string pno);
void Hangup();
void Send( char c);
char Recv();
}

然而,该接口中却显示出两个职责。第一:链接管理;第二:数据通信。Dial和Hangup方法进行调制解调器的链接处理,而Send和recv方法进行数据通信。

这两个职责应该分开吗?这依赖于应用程序的变化方式。如果应用程序的变化会影响到链接方法的签名(signature),那么这个设计就具有僵化性的臭味,因为调用Send和Recv的类必须要重新编译、部署的次数常常会超过我们希望的次数。在这种情况下,这两个职责应该被分离,如下图。这样做避免了客户应用程序和这两个职责耦合在一起。

3

另一方面,如果应用程序的变化方式总是导致这两个职责同时变化,那么就不必分离他们。这时,分离它们就会具有不必要的复杂性的臭味。

仅当变化发生时,变化的轴线(职责)才具有实际的意义。

我们把两个职责都耦合进了ModemImplementation类中,这不是所希望的,但或许是必要的,常常由于一些和硬件或者操作系统的细节有关的原因,迫使我们这样去处理。我们可以把它看做一个有缺陷的类,所有的依赖关系都是从它出发,谁也不需要依赖它。除了Main以为,谁也不需要知道它的存在。因此我们已经把丑陋的部分隐藏起来。



2. OCP 开闭原则,很简单,一句话:“Closed for Modification; Open forExtension”——“对变更关闭;对扩展开放”。开闭原则其实没什么好讲的,我将其归结为一个高层次的设计总则。OCP的动机很简单:软件是变化的。不论是优质的设计还是低劣的设计都无法回避这一问题。OCP说明了软件设计应该尽可能地使架构稳定而又容易满足不同的需求。为什么要OCP?答案也很简单——重用。

开闭原则是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。 所谓的开闭原则(Open-Closed Principle,简称 OCP)说的是:软件实体(类、模块、功能等)应该可以被扩展,但不可被修改。开闭原则说白了就是,应该在不修改现有代码的基础上,引入新功能。
开闭原则中的“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中的“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。
而实际上,要做到百分之百的封闭是不可能的,但是在系统设计的时候,还是应该尽量做到这一点。
一个简单的例子,假设现在需要实现一个加法的功能,很简单,如图示1:

现在的问题是,需求变了,要求还要实现一个减法的功能,这也很简单,如图示2:

如果需求再变,还要求能实现乘法和除法的功能,依然简单,如图示3:


从第2和第3步来看,很明显,在需求改变,需要引进新的功能的时候,做法是在已有的类的基础上通过新添方法来实现功能,假设在第2步之后,第3步的时候发现加法和减法功能最终都没有用到,反而乘法和除法需要用到,那么在第3步的时候就要推翻第2步之前的实现,在需求发生改变需要引进新的功能的时候,就要推翻整个之前的系统,很明显这样的做法是不可取的,说明设计上出现了问题,这个缺陷明显的是违反了OCP(开闭原则)。
需求总是在变的,如果可能,就要做到尽量不要去修改已有的实现,而应该通过扩展的手段来稳定需求的变动。

OCP原则替换图2:

OCP原则替换图3:


在我们最初编写代码的时候,我们假设变化不会发生,但最后变化发生的时候,可以通过创建抽象来隔离以后将要发生的同类变化。
开闭原则是面向对象设计中“可复用设计”的基础,是面向对象设计中最重要的原则之一。 从开闭原则中可以看出,面对对象的重要原则是创建抽象化,并且从抽象化中导出具体化,具体化可以有许多不同的版本,而每个不同的版本可以给出不同的实现。
出处:http://www.blogjava.net/fancydeepin ]

3. LSP(Liskov Substitution Priciple)里氏替换原则 
  Liskov于1987年提出了一个关于继承的原则“Inheritanceshould ensure that any property proved about supertype objects alsoholds for subtypeobjects.”——“继承必须确保超类所拥有的性质在子类中仍然成立。”也就是说,当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系。   该原则称为LiskovSubstitution Principle——里氏替换原则。  
我们来研究一下LSP的实质。学习OO的时候,我们知道,一个对象是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。LSP所表述的就是在同一个继承体系中的对象应该有共同的行为特征。
LSP讲的是基类和子类的关系。只有当这种关系存在时,里氏代换关系才存在。如果两个具体的类A,B之间的关系违反了LSP的设计,(假设是从B到A的继承关系)那么根据具体的情况可以在下面的两种重构方案中选择一种。创建一个新的抽象类C,作为两个具体类的超类,将A,B的共同行为移动到C中来解决问题。从B到A的继承关系改为委派关系。 

里氏置换原则(Liskov Substitution Principle),简称LSP

定义:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基类的地方必须能够透明的使用其子类对象。

也就是说,只要父类出现的地方子类就能够出现,而且替换为子类不会产生任何错误或异常。但是反过来,子类出现的地方,替换为父类就可能出现问题了。

这个原则是为良好的继承定义一个规范,简单的讲,有4层含义:

一、子类必须完全实现父类的方法

定义一个抽象类

public abstract class ViewPoint {
//去丽江旅游
public abstract void where();
}

下面两个类是实现这个抽象类

public class Lijiang extends ViewPoint {
@Override
public void where() {
System.out.println( "欢迎来到丽江..." );
}
}


public class Zhangjiajie extends ViewPoint {
@Override
public void where() {
System.out.println( "欢迎来到张家界..." );
}
}

人物是涂涂,在里面设置类类型来传递参数。此时涂涂要去的旅游景点还是抽象的

public class Tutu {
//定义要旅游的景点
private ViewPoint viewpoint;
//涂涂要去的景点
public void setViewPoint(ViewPoint viewpoint)
{
this .viewpoint = viewpoint;
}
public void travelTo()
{
System.out.println( "涂涂要去旅游了" );
viewpoint.where();
}
}

场景类。设置具体要去的景点

public class Sence {
public static void main(String args[])
{
Tutu tutu = new Tutu();
//设置要去的旅游景点
tutu.setViewPoint( new Lijiang());
tutu.travelTo();
}
}

运行结果:

涂涂要去旅游了
欢迎来到丽江...

二、子类可以有自己的特性

也就是说在类的子类上,可以定义其他的方法或属性

三、覆盖或者实现父类的方法时输入参数可以被放大

父类能够存在的地方,子类就能存在,并且不会对运行结果有变动。反之则不行。

父类,say()里面的参数是HashMap类型,是Map类型的子类型。(因为子类的范围应该比父类大)


import java.util.Collection;
import java.util.HashMap;
public class Father {
public Collection say(HashMap map)
{
System.out.println( "父类被执行..." );
return map.values();
}
}

子类,say()里面的参数变成了Map类型,Map范围比HashMap类型大,符合LSP原则。注意这里的say不是覆写父类的say,因为参数类型不同。而是重载。

import java.util.Collection;
import java.util.Map;
/*
* 子类继承了父类的所有属性
*/
public class Son extends Father {
//方法输入参数类型
public Collection say(Map map)
{
System.out.println( "子类被执行..." );
return map.values();
}
}

场景类

import java.util.HashMap;
public class Home {
public static void main(String args[])
{
invoke();
}
public static void invoke()
{
//父类存在的地方,子类就应该能够存在
//Father f = new Father();
Son s = new Son();
HashMap map = new HashMap();
//f.say(map);
s.say(map);
}
}

无论是用父类还是子类调用say方法,得到的结果都是

父类被执行...

但是,如果将上面Father里的say参数改为Map,子类Son里的say参数改为HashMap,得到的结果就变成了

f.say(map)结果:父类被执行...
s.say(map)结果: 子类被执行...

这样会造成逻辑混乱。所以子类中方法的前置条件必须与父类中被覆写的前置条件相同或者更宽。

四、覆写或者实现父类的方法时输出结果可以被缩小

其实与上面的类似,也就是父类能出现的地方子类就可以出现,而且替换为子类不会产生任何错误或者异常,使用者也无需知道是父类还是子类。但是反过来就不行了,有子类出现的地方,父类未必就适应。(毕竟子类的范围要>=父类的范围)



4.DIP 依赖倒置原则 
依赖倒置(Dependence InversionPrinciple)原则讲的是:要依赖于抽象,不要依赖于具体。 
简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述: 
抽象不应当依赖于细节;细节应当依赖于抽象; 
要针对接口编程,不针对实现编程。 

依赖倒置原则(Dependence Inversion Principle),简称DIP

定义

High level modules should depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

1、高层模块不应该依赖低层模块,两者都应该依赖于抽象(抽象类或接口)

2、抽象(抽象类或接口)不应该依赖于细节(具体实现类)

3、细节(具体实现类)应该依赖抽象

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

细节:即具体的实现类,实现接口或者继承抽象类所产生的类,两者可以通过关键字new直接被实例化

而依赖倒置原则的本质骑士就是通过抽象(抽象类或接口)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合。但是这个原则也是6个设计原则中最难以实现的了,如果没有实现这个原则,那么也就意味着开闭原则(对扩展开发,对修改关闭)也无法实现。

依赖倒置有三种方式来实现

1、通过构造函数传递依赖对象

比如在构造函数中的需要传递的参数是抽象类或接口的方式实现。

2、通过setter方法传递依赖对象

即在我们设置的setXXX方法中的参数为抽象类或接口,来实现传递依赖对象

3、接口声明实现依赖对象

例如下面的例子

涂涂是个女僧

public class Tutu {
//涂涂是个女孩,会煮面
public void cook(Noodles noodles)
{
noodles.eat();
}
}

面条(目前只会煮面)
public class Noodles {
//吃面条
public void eat()
{
System.out.println( "涂涂吃面条..." );
}
}

涂涂坐在家里吃面(场景类)

public class Home {
public static void main(String args[])
{
Tutu tutu = new Tutu();
Noodles food = new Noodles();
tutu.cook(food);
}
}

运行结果:涂涂吃面条...

但是这有个问题,涂涂只会做面条,不可能每次都吃面条吧,天天吃面吃死你,所以在上面的Tutu类中的cook方法中,如果涂涂会做其他吃的,那岂不是更好。于是她向家庭主妇迈进了一步,使用了依赖倒置原则。

也就是涂涂通过学习还可以焖米饭,炒鱿鱼(虽然听着不爽,但是很好吃),京酱肉丝啊等等。要想在代码中实现,就需要实现两个接口:ITutu和IFood

public interface ITutu {
//这样就会做很多饭菜了
public void cook(IFood food);
}

实现类
public class Tutu implements ITutu {
@Override
public void cook(IFood food) {
food.eat();
}
}

食物接口
public interface IFood {
public void eat();
}

这样就为扩展留出了很大的空间,方面扩展其他的类。也不会对细节有变动。以后涂涂想吃什么学一下就可以自己做了

实现面条

public class Noodles implements IFood {
@Override
public void eat() {
System.out.println( "涂涂吃面条..." );
}
}

实现米饭

public class Rice implements IFood {
@Override
public void eat() {
System.out.println( "涂涂吃米饭(终于吃上米饭了)..." );
}
}

场景类:涂涂在家里开吃了,想吃什么直接做就是了

public class Home {
public static void main(String args[])
{
//接口使不能实例化滴
ITutu tutu = new Tutu();
//实例化米饭,涂涂可以吃米饭了
IFood rice = new Rice();
//吃面条
//IFood noodles = new Noodles();
tutu.cook(rice);
}
}

这样各个类或模块的实现彼此独立,不互相影响,实现了模块间的松耦合。


5.ISP (Interface SegregationPrinciple)接口隔离原则 
使用多个专门的接口比使用单一的总接口要好。广义的接口:一个接口相当于剧本中的一种角色,而此角色在一个舞台上由哪一个演员来演则相当于接口的实现。因此一个接口应当简单的代表一个角色,而不是一个角色。,如果系统设计多个角色的话,则应当每一个角色都由一个特定的接口代表。狭义的接口(Interface):接口隔离原则讲的就是同一个角色提供宽、窄不同的接口,以对付不同的客户端。

一、原理介绍

回到顶部

1、官方定义

接口隔离原则,英文缩写ISP,全称Interface Segregation Principle。

原始定义:Clients should not be forced to depend upon interfaces that they don't use,还有一种定义是The dependency of one class to another one should depend on the smallest possible interface。

官方翻译:其一是不应该强行要求客户端依赖于它们不用的接口;其二是类之间的依赖应该建立在最小的接口上面。简单点说,客户端需要什么功能,就提供什么接口,对于客户端不需要的接口不应该强行要求其依赖;类之间的依赖应该建立在最小的接口上面,这里最小的粒度取决于单一职责原则的划分。

回到顶部

2、自己理解

2.1、原理解释

  • 不应该强行要求客户端依赖于它们不用的接口。语句很好理解,即客户端需要什么接口,就依赖什么接口,不需要的就不依赖。那么我们反过来说,如果客户端依赖了它们不需要的接口,那么这些客户端程序就面临不需要的接口变更引起的客户端变更的风险,这样就会增加客户端和接口之间的耦合程度,显然与“高内聚、低耦合”的思想相矛盾。
  • 类之间的依赖应该建立在最小的接口上面。何为最小的接口,即能够满足项目需求的相似功能作为一个接口,这样设计主要就是为了“高内聚”。那么我们如何设计最小的接口呢?那就要说说粒度的划分了,粒度细化的程度取决于我们上一章讲的的 单一职责原则里面接口划分的粒度。从这一点来说,接口隔离和单一职责两个原则有一定的相似性。

2.2、接口隔离原则和单一职责原则

从功能上来看,接口隔离和单一职责两个原则具有一定的相似性。其实如果我们仔细想想还是有区别的。

(1)从原则约束的侧重点来说,接口隔离原则更关注的是接口依赖程度的隔离,更加关注接口的“高内聚”;而单一职责原则更加注重的是接口职责的划分。

(2)从接口的细化程度来说,单一职责原则对接口的划分更加精细,而接口隔离原则注重的是相同功能的接口的隔离。接口隔离里面的最小接口有时可以是多个单一职责的公共接口。

(3)单一职责原则更加偏向对业务的约束,接口隔离原则更加偏向设计架构的约束。这个应该好理解,职责是根据业务功能来划分的,所以单一原则更加偏向业务;而接口隔离更多是为了“高内聚”,偏向架构的设计。

回到顶部

二、场景示例

下面就以订单的操作为例来说明下接口隔离的必要性。

回到顶部

1、胖接口

 软件设计最初,我们的想法是相同功能的方法放在同一个接口里面,如下,所有订单的操作都放在订单接口IOrder里面。理论上来说,这貌似没错。我们来看看如何设计。

复制代码
   public interface IOrder
    {
        //订单申请操作
        void Apply(object order);

        //订单审核操作
        void Approve(object order);

        //订单结束操作
        void End(object order);

    }
复制代码

刚开始只有销售订单,我们只需要实现这个接口就好了。

复制代码
    public class SaleOrder:IOrder
    {
        public void Apply(object order)
        {
            throw new NotImplementedException();
        }

        public void Approve(object order)
        {
            throw new NotImplementedException();
        }

        public void End(object order)
        {
            throw new NotImplementedException();
        }
    }
复制代码

后来,随着系统的不断扩展,我们需要加入生产订单,生产订单也有一些单独的接口方法,比如:排产、冻结、导入、导出等操作。于是我们向订单的接口里面继续加入这些方法。于是订单的接口变成这样:

复制代码
    public interface IOrder
    {
        //订单申请操作
        void Apply(object order);

        //订单审核操作
        void Approve(object order);

        //订单结束操作
        void End(object order);

        //订单下发操作
        void PlantProduct(object order);

     //订单冻结操作
        void Hold(object order);

        //订单删除操作
        void Delete(object order);

        //订单导入操作
        void Import();

        //订单导出操作
        void Export();
    }
复制代码

我们生产订单的实现类如下

复制代码
    //生产订单实现类
    public class ProduceOrder : IOrder
    {
        /// <summary>
        /// 对于生产订单来说无用的接口
        /// </summary>
        /// <param name="order"></param>
        public void Apply(object order)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 对于生产订单来说无用的接口
        /// </summary>
        /// <param name="order"></param>
        public void Approve(object order)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 对于生产订单来说无用的接口
        /// </summary>
        /// <param name="order"></param>
        public void End(object order)
        {
            throw new NotImplementedException();
        }

        public void PlantProduct(object order)
        {
            Console.WriteLine("订单下发排产");
        }

     public void Hold(object order)
        {
            Console.WriteLine("订单冻结");
        }

        public void Delete(object order)
        {
            Console.WriteLine("订单删除");
        }

        public void Import()
        {
            Console.WriteLine("订单导入");
        }

        public void Export()
        {
            Console.WriteLine("订单导出");
        }
    }
复制代码

 销售订单的实现类也要相应做修改

复制代码
    //销售订单实现类
    public class SaleOrder:IOrder
    {
        public void Apply(object order)
        {
            Console.WriteLine("订单申请");
        }

        public void Approve(object order)
        {
            Console.WriteLine("订单审核处理");
        }

        public void End(object order)
        {
            Console.WriteLine("订单结束");
        }

        #region 对于销售订单无用的接口方法
        public void PlantProduct(object order)
        {
            throw new NotImplementedException();
        }

     public void Hold(object order)
        {
            throw new NotImplementedException();
        }

        public void Delete(object order)
        {
            throw new NotImplementedException();
        }

        public void Import()
        {
            throw new NotImplementedException();
        }

        public void Export()
        {
            throw new NotImplementedException();
        } 
        #endregion
    }
复制代码

需求做完了,上线正常运行。貌似问题也不大。系统运行一段时间之后,新的需求变更来了,要求生成订单需要一个订单撤销排产的功能,那么我们的接口是不是就得增加一个订单撤排的接口方法CancelProduct。于是乎接口变成这样:

复制代码
public interface IOrder
    {
        //订单申请操作
        void Apply(object order);

        //订单审核操作
        void Approve(object order);

        //订单结束操作
        void End(object order);

        //订单下发操作
        void PlantProduct(object order);

        //订单撤排操作
        void CancelProduct(object order);

        //订单冻结操作
        void Hold(object order);

        //订单删除操作
        void Delete(object order);

        //订单导入操作
        void Import();

        //订单导出操作
        void Export();
    }
复制代码

这个时候问题就来了,我们的生产订单只要实现这个撤销的接口貌似就OK了,但是我们的销售订单呢,本来销售订单这一块我们不想做任何的变更,可是由于我们IOrder接口里面增加了一个方法,销售订单的实现类是不是也必须要实现一个无效的接口方法?这就是我们常说的“胖接口”导致的问题。由于接口过“胖”,每一个实现类依赖了它们不需要的接口,使得层与层之间的耦合度增加,结果导致了不需要的接口发生变化时,实现类也不得不相应的发生改变。这里就凸显了我们接口隔离原则的必要性,下面我们就来看看如何通过接口隔离来解决上述问题。

2、接口隔离

我们将IOrder接口分成两个接口来设计

复制代码
    //删除订单接口
    public interface IProductOrder
    {
        //订单下发操作
        void PlantProduct(object order);

        //订单撤排操作
        void CancelProduct(object order);

        //订单冻结操作
        void Hold(object order);

        //订单删除操作
        void Delete(object order);

        //订单导入操作
        void Import();

        //订单导出操作
        void Export();
    }

    //销售订单接口
    public interface ISaleOrder
    {
        //订单申请操作
        void Apply(object order);

        //订单审核操作
        void Approve(object order);

        //订单结束操作
        void End(object order);
    }
复制代码

对应的实现类只需要实现自己需要的接口即可

复制代码
    //生产订单实现类
    public class ProduceOrder : IProductOrder
    {
        public void PlantProduct(object order)
        {
            Console.WriteLine("订单下发排产");
        }

        public void CancelProduct(object order)
        {
            Console.WriteLine("订单撤排");
        }

        public void Hold(object order)
        {
            Console.WriteLine("订单冻结");
        }

        public void Delete(object order)
        {
            Console.WriteLine("订单删除");
        }

        public void Import()
        {
            Console.WriteLine("订单导入");
        }

        public void Export()
        {
            Console.WriteLine("订单导出");
        }
    }

    //销售订单实现类
    public class SaleOrder : ISaleOrder
    {

        public void Apply(object order)
        {
            Console.WriteLine("订单申请");
        }

        public void Approve(object order)
        {
            Console.WriteLine("订单审核处理");
        }

        public void End(object order)
        {
            Console.WriteLine("订单结束");
        }
    }
复制代码

这样设计就能完美解决上述“胖接口”导致的问题,如果需要增加订单操作,只需要在对应的接口和实现类上面修改即可,这样就不存在依赖不需要接口的情况。通过这种设计,降低了单个接口的复杂度,使得接口的“内聚性”更高,“耦合性”更低。由此可以看出接口隔离原则的必要性。

回到顶部

三、总结

通过以上订单功能的优化,我们看到了接口隔离原则的必要性,当然,关于接口隔离原则和单一职责原则的细节我们也不必过多追究,不管何种原则,能解决我们的设计问题就是好的原则、我们必须遵守的原则。欢迎园友拍砖斧正。如果园友们觉得本文对你有帮助,请帮忙推荐,博主将继续努力~~


六大设计原则之 里氏替换原则 (Liskov Substitution Principle | LSP
心有猛虎 细嗅蔷薇
07-18 484
目录 前言 里氏替换原则 定义 场景 特点 优点 栗子 正例 特例1 特例2 前言 OO(Object Oriented 面向对象) 设计的六大原则OCP(开闭原则),DIP(依赖倒置原则),ISP(接口隔离原则),LSP(里氏替换原则),SRP(单一职责原则),LKP(迪米特法则) 里氏替换原则 定义 面向对象的基本设计原则之一,里氏替换原则中说,任何基类可以出现...
面向对象设计原则SRPOCPLSPDIPISP
08-31
面向对象 设计原则 单一职责原则--SRP 开放封闭原则--OCP Liskov替换原则--LSP 依赖倒置原则--DIP 接口隔离原则--ISP
敏捷开发之原则 五大原则 SRP OCP LSP DIP ISP
热门推荐
心之所向
02-08 1万+
一、面向对象设计原则内容来自《敏捷开发:原则、模式与实例》 SRP单一职责原则(Single Responsibility Principle): 就一个类而言,应该仅有一个引起它变化的原因。 OCP开放-封闭原则(Open Closure Principle): 软件实体(类,模块,函数等)应该可以扩展的,但不可修改。 LSPLiskov 替换原则(Liskov Substitution
设计模式六大原则详解
最新发布
weixin_43298211的博客
08-17 952
类的功能应当尽可能单一化,如果一个类承担了多个职责,则当其中一个职责发生变化时,可能会影响到其他职责,从而导致代码难以维护。: 如果一个程序使用的是父类的一个对象,那么用子类的对象来替换它时,程序的行为不应该发生任何变化。: 当应用程序的需求改变时,可以通过增加新的代码来满足新需求,而不是修改现有的代码。: 接口中定义的方法应该尽可能地具体,以避免出现客户端不需要使用的方法。: 软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改的。: 每个类都应当减少对外部类的依赖,只与直接的朋友通信。
敏捷实践:SRP OCP LSP DIP ISP原则
weixin_30508241的博客
07-16 321
敏捷开发提倡简单设计的实践,“并在实现新需求时抓住机会改进设计”以对同类性质的改动封闭,做到由需求的变化驱动设计的进化(我们不能因为设计的退化而责怪需求的变化),同时经验在此起到十分重要的作用,如有经验的设计人员可以凭经验在初始设计时做出必要的抽象来满足ocp原则等,或是在需求变动时确定系统所需的抽象(所需的封闭),当然应及早的刺激这种变化的出现(如测试驱动的开发方法)。   OOD承诺了一系列...
OO五大原则
温柔一刀
07-14 182
OO五大原则SRPOCPLSPDIPISP 1. SRP(Single Responsibility Principle 单一职责原则) 单一职责很容易理解,所谓单一职责,就是一个设计元素只做一件事。 2. OCP (Open Close Principle 开闭原则) 一句话:“Closed for Modification; Open for Extensio...
系统设计原则--SRP OCP LSP DIP ISP
numenshane1的专栏
12-13 2120
一、单一职责原则SRP)      每个类应当只负责单一内聚的职责,每一个职责都是变化的一个轴线,当需求变化时,该变化会反映为类的职责的变化。一个类应当仅有一个引起它变化的原因,如果一个类承担了多于一个的职责,那么引起它变化的原因就会有多个,等于把这些职责耦合在了一起。违反SRP的设计通常可以采用门面模式或代理模式进行重构,分离业务的职责。二、开闭原则OCP)      软件实体(类、包、模块等)应该是可以扩展的,但是不可修改的,即对于扩展是开放的,对于修改是封闭的,对实体的行为扩展时,无需改动源代码或
OO五大原则SRPOCPLSPDIPISP
Staid's Space
11-24 5733
<br />OO五大原则SRPOCPLSPDIPISP。<br />SRP -- (Single Responsibility Principle 单一职责原则)<br />OCP——开闭原则(Closed for Modification; Open for Extension)<br /> 现将近期整理的文档提供给大家,这里对LSP做重点的介绍,望对大家有帮助,在学习和使用OO设计的时候,我们应该明白:OO的出现使得软件工程师们能够用更接近真实世界的方法描述软件系统。然而,软件毕竟是建立在
面向对象编程,OO设计的五大原则
07-12
在本文中,我们将详细探讨OOP设计中的五大原则:单一职责原则(Single Responsibility Principle,简称 SRP)、开放封闭原则(Open-Closed Principle,简称 OCP)、里氏替换原则(Liskov Substitution Principle,...
第七讲-面向对象程序的需求分析与设计原则v4.01
08-03
面向对象程序的需求分析与设计原则是软件开发中的关键步骤,特别是在OO面向对象)编程范式下。这一讲主要探讨如何有效地进行面向对象程序的需求分析,以及遵循的设计原则,以确保软件的质量、可维护性和扩展性。 ...
面向对象三大特性五大原则 + 低耦合高内聚
阅读之后,对你有帮助,那就点个赞再走吧
04-02 272
面向对象的三大特性是"封装、"多态"、"继承",五大原则是"单一职责原则"、"开放封闭原则"、"里氏替换原则"、"依赖倒置原则"、"接口分离原则"。 什么是面向对象 面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。面向...
OO五大原则中的 LSP(zt)
guohui_fz
01-18 571
OO五大原则中的 LSP(里氏替换原则) 现将近期整理的文档提供给大家,这里对LSP做重点的介绍,望对大家有帮助,在学习和使用OO设计的时候,我们应该明白:OO的出现使得软件工程师们能够用更接近真实世界的方法描述软件系统。然而,软件毕竟是建立在抽象层次上的东西,再怎么接近真实,也不能替代真实或被真实替代。 OO设计的五大原则之间并不是相互孤立的。彼此间存在着一定关联,一个可以是另...
OO五大原则SRPOCPLSPDIPISP
12-09 219
OO五大原则SRPOCPLSPDIPISP oo面向对象 srp 单一职责原则 单一职责原则 ocp 对扩展开放,对修改关闭原则 lsp 里氏替换原则 dip 依赖倒置原则 依赖接口 不要依赖具体实例 isp 接口隔离原则 使用多个专门的接口比使用单一的总接口要好。 转载于:https://www.cnblogs.com/wholeworld/p/80...
【设计原则五大原则 SRP OCP LSP DIP ISP
keeper42的博客
01-21 749
https://blog.csdn.net/qq_16234613/article/details/54933742 SRP单一职责原则(Single Responsibility Principle):   就一个类而言,应该仅有一个引起它变化的原因。 OCP开放-封闭原则(Open Closure Principle):   软件实体(类,模块,函数等)应该可以扩展的,但不可修改。 ...
UML中的 SRPOCPLSPDIP、CARP的中英文全称和意义
拥抱变化
10-09 3241
OOA的全称Object-Oriented Analysis 面向对象分析方法 意义(1)加强了对问题域和系统责任的理解;   (2)改进与分析有关的各类人员之间的交流;   (3)对需求的变化具有较强的适应性;   (4)支持软件复用;   (5)贯穿软件生命周期全过程的一致性。   (6)实用性;   (7)有利于用户参与。 OOD的全称Object-Oriented Desi
【Spring】OCP,DIP原则,IoC思想和依赖注入DI重点知识汇总
qq_68993495的博客
02-05 1129
本章内容: OCP原则, 依赖倒置DIP原则, 控制反转IoC思想, 依赖注入DI, 第一个spring程序的注意细节.
ssm框架学习开端之OCP开闭原则DIP原则
快乐学习
02-02 521
反之,如果在扩展功能的时候,修改了之前的代码,那么这个设计是失败的,违背ocp原则。在扩展系统功能时,没有修改以前的代码,那么就是符合ocp原则的。这个是所有软件开发都是一样的通用道理,不单单是针对某一个开发语言。其他的六个原则都是为这个原则服务的。二、ocp的地位作用?ocp原则是最核心,最基本的,其他的六个原则都是为这个原则服务的。
设计模式——七大设计原则
weixin_43412762的博客
12-05 3015
设计模式的七大原则:开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则
面向对象设计基本原则之单一职责原则
shanshan2099的专栏
10-29 279
单一职责原则,Single Responsibility Principle,简称SRP。 其定义是一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。 单一职责原则是实现高内聚低耦合的知道方针,是最简单却最难运用的原则,需要设计人员发现类的不同职责并将其分离 优点: 1.类的复杂性降低,实现什么职责都有清晰明确的定义 2.可读性提高,复杂性降低 3.可维护性提高,可读性提高 4.变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口将修改只对相应的实..
写文章

热门文章

  • fatal: Could not read from remote repository.的解决办法 274792
  • tomcat部署项目时出错(Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardC) 76442
  • Oracle数据库插入CLOB字段时,提示ORA-01704:字符串文字太长【解决方案】 50971
  • JS将科学计数法字串转换成正常数值 28618
  • springMVC接受list报错:Could not instantiate bean class [java.util.List]: Specified class is an interf 27033

分类专栏

  • Editplus 操作与技巧 6篇
  • Java 140篇
  • javascript 52篇
  • jQuery 12篇
  • JSP 11篇
  • oracle 18篇
  • 思想 49篇
  • 技巧 22篇
  • 杀毒防黑 2篇
  • Eclipse & MyEclipse 27篇
  • tomcat 7篇
  • mysql 16篇
  • firefox浏览器技巧 4篇
  • windows 7篇
  • linux 1篇
  • nutz 1篇
  • svn 4篇
  • 新闻及其他 4篇
  • memcash 2篇
  • aptana 1篇
  • sql 16篇
  • 项目发布 1篇
  • struts2 4篇
  • hibernate 2篇
  • spring 10篇
  • maven 6篇
  • 项目管理 2篇
  • dom4j 2篇
  • css及相关 16篇
  • dwr 2篇
  • 硬件及相关 6篇
  • 代码调试 1篇
  • git 5篇
  • 异常 8篇
  • php相关 2篇
  • selenium自动化测试 16篇
  • log4j相关 4篇
  • Android 1篇
  • 测试相关 1篇
  • hadoop 1篇
  • jenkins自动发布 2篇
  • mybatis 23篇
  • Flexigrid 6篇
  • 正则
  • 正则表达式 1篇
  • 一个典型的 jquery flexigrid配置
  • freemarker 8篇
  • springMVC 14篇
  • excel导出模板jstl 1篇
  • jxls-excel导出模板
  • eChart 1篇
  • ang
  • angularJS 1篇
  • xiangmu
  • java8 18篇
  • Jxls导出exce 1篇
  • solr 1篇
  • redis 2篇
  • url 1篇
  • JVM内存 5篇
  • html 1篇
  • bootstrapTable 2篇
  • 设计模式 2篇
  • 谷歌浏览器 1篇
  • 二维码 1篇
  • uml 1篇

最新评论

  • 解决Maven项目相互依赖/循环依赖/双向依赖的问题

    qq_50874796: 我也觉得不能循环依赖这个真的很反人类,但凡这两个互相依赖的模块可以合并,当初何必设计成2个不同的模块呢表情包

  • 解决Maven项目相互依赖/循环依赖/双向依赖的问题

    我是死宅萝莉控: 那maven这种分模块开发有什么优点吗?为啥不直接在一个模块开发就没有这种依赖的问题了。

  • fatal: Could not read from remote repository.的解决办法

    海岸HaiAn: 有用,感谢。 解决了我的 git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. 报错问题

  • fatal: Could not read from remote repository.的解决办法

    sinat_39619570: thx!!!

  • META-INF文件夹是干啥的,META-INF文件夹的作用, META-INF文件夹能删吗

    小可爱网络科技: 就是啊 说了一个寂寞 我怀疑他是来逗我们玩的表情包

最新文章

  • HttpClient实现 get、post、put、delete请求【转】
  • Java - 格式化输出JSON字符串的两种方式
  • Oracle的硬解析和软解析
2023年1篇
2021年2篇
2020年1篇
2019年5篇
2018年27篇
2017年122篇
2016年47篇
2015年72篇
2014年71篇
2013年104篇
2012年61篇
2011年3篇
2010年6篇
2009年8篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家上海常见商场美陈价格玻璃钢观音雕塑江苏玻璃钢雕塑摆件供货商腾冲市玻璃钢雕塑费用多少常德岳阳玻璃钢雕塑设计玻璃钢花盆定制厂家哈尔滨玻璃钢雕塑生产厂家商场美陈主管大型玻璃钢雕塑摆件定制抽象玻璃钢人物雕塑制作黄石定做玻璃钢雕塑达州玻璃钢造型雕塑溧阳商场美陈广东佛像玻璃钢雕塑订做价格大型校园玻璃钢景观雕塑报价湛江玻璃钢葡萄雕塑加工定做玻璃钢迎宾人物雕塑无锡河北定制玻璃钢迎宾人物雕塑山东艺术商场美陈销售上海玻璃钢卡通雕塑渝北玻璃钢人物雕塑渭南玻璃钢雕塑制作厂家河南玻璃钢雕塑报价济源玻璃钢雕塑仙鹤生产厂河北玻璃钢雕塑设计玻璃钢鞋雕塑东方韵艺术玻璃钢卡通动漫雕塑云南多彩玻璃钢雕塑设计宁德玻璃钢花盆厂盐城五一商场美陈香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化