里氏代换原则

合集下载

软件设计原则---六大原则

软件设计原则---六大原则

软件设计原则---六⼤原则软件设计原则这是⼀篇关于软件设计六⼤原则的学习笔记,今天得知了⼀些不太让⼈开⼼的事情,感叹⼈⽣起起落落,彷徨间学不进新东西,只好⼜写起了博客写完以后⼼情好了些,可能⼈⽣就是应当少⽣些繁杂思绪,只得去做,去体验,最后⽅能修得⼼绪宁静⾃得之镜吧在软件开发中,程序员应尽量遵守这六条软件设计原则,这六条原则可以帮助我们提⾼软件系统的可维护性和可复⽤性,增加软件的可拓展性和灵活性。

软件设计六⼤原则:开闭原则⾥⽒代换原则依赖倒转原则接⼝隔离原则迪⽶特法则合成复⽤原则1、开闭原则对拓展开放,对修改关闭在程序需要拓展原有功能时,不能对原有代码进⾏修改,⽽要实现⼀个热插拔的效果:需要什么就添加上去,不要影响原来的程序功能。

其⽬的在于使得程序可拓展性好,易于维护与升级。

要想达到这样的效果,我们需要使⽤接⼝和抽象类。

为什么呢?其实本质上接⼝和抽象类定义的就是规范,只要我们合理的抽象,它可以覆盖很⼤的⼀块功能实现,从⽽维持软件架构的稳定。

⽽那些易变的细节,则可以交给具体的实现类来完成,当软件需求发⽣变化,只需要再派⽣⼀个实现类完成功能即可。

这⾥某种程度上其实暗合了依赖倒转原则。

实现开闭原则简单实例:我们创建⼀个代表⽪肤展⽰的接⼝,然后通过多个类实现该接⼝来完成⽪肤的实现,最后通过⼀个测试类来进⾏测试。

//接⼝,表⽰⽪肤展⽰的抽象意义public interface Skin {void showSkin();}//实现类⼀,实现了第⼀种⽪肤的展⽰public class ShowSkin01 implements Skin {@Overridepublic void showSkin() {System.out.println("Skin01");}}//实现类⼆,实现了第⼆种⽪肤的展⽰public class ShowSkin02 implements Skin {@Overridepublic void showSkin() {System.out.println("Skin02");}}//IoC简单实现,将选择何种⽪肤的权利交给⽤户public class Shower {private Skin skin;public void setSkin(Skin skin) {this.skin = skin;}public void show(){skin.showSkin();}}//客户端,如果输⼊1,则展⽰⽪肤1;如果输⼊2,则展⽰⽪肤2;其他输⼊会显⽰⽆效输⼊public class Client {public static void main(String[] args) {Shower shower = new Shower();Scanner scanner = new Scanner(System.in);int i = scanner.nextInt();switch (i){case 1:shower.setSkin(new ShowSkin01());shower.show();break;case 2:shower.setSkin(new ShowSkin02());shower.show();break;default:System.out.println("input no sense!");}}}2、⾥⽒代换原则任何⽗类出现的地⽅,⼦类⼀定也可以出现通俗理解就是,⼦类可以拓展⽗类的功能,补充原来没有的功能,但是,不能改变⽗类原有的功能。

面向对象个人心得体会

面向对象个人心得体会

面向对象个人心得体会篇一:面向对象的编程总结一、什么是面向对象:所谓面向对象的编程就是:通过封装,继承,多态,把程序的耦合度降低,传统的雕版印刷术的问题就在于所有刻字都在同一版面上造成耦合度太高所致,当用面向对象的模式,使得印刷程序更加灵活,容易修改,并且易于复用。

对象(Object)是类(Class)的一个实例(Instance)。

如果将对象比作房子,那么类就是房子的设计图纸。

所以面向对象程序设计的重点是类的设计,而不是对象的设计。

类可以将数据和函数封装在一起,其中函数表示了类的行为(或称服务)。

类提供关键字public、protected 和private 用于声明哪些数据和函数是公有的、受保护的或者是私有的。

二:基类类与结构体的区别和联系; Strcut test{Private:Int number; Public:Float socre; };类的创建方式和结构体几乎一样, Class test {Private:Int number; Public:Float socre;Public:Public:Int rp();{ Return number;}Void setnum(int a) {Number=a; }}; 但是大家注意到没有,标准c中不允许在结构体中声明函数的,但是在c++中的类中是可以的,这就和c有了本质的区别,很好体现了c++面向对象的特点。

两种语言的区别:过去的c语言是一种面向过程的语言特性是:程序=算法+数据结构但c++的特性是:对象=算法+数据结构;程序=对象+对象+对象。

区别:在c语言中个成员他们的默认存储控制是public 而c++类中默认的存储控制是private.; 上面的rp()事成员函数,如果我们有如下定义: Test a;的话,调用rp()就可以写成: a. rp();成员函数的调用和普通成员的调用方式一致都采用“.”的操作符。

例如: class test {private://私有成员类外不能够直接访问 int number;public://共有成员类外可以直接访问 float socre; public: int rp() {return number; } void setnum(int a) {number=a; } };void main() { test a; //a.number=10;//错误的,私有成员不能外部访问 a.socre=99.9f; cout<<a.socre<<endl;a.setnum(100);//通过共有成员函数setnum()间接对私有成员number函数进行访问 cout<<a.rp(); cout<<endl; }/*int pp=0; class test {private: int number; public: float socre; int pp; public: void rp(); };void test::rp() { ::pp=11; pp=100; }void main() { test a; test b; a.rp(); cout<<pp<<endl; cout<<a.pp<<endl; }*/利用域区分符我们可以在类定义的外部设置成员函数,但要注意的是,在类的内部必须预声明:类型类名 :: 函数名()=值void test::rp()在函数类型的后面加上类的名称再加上域区分符(::)再加函数名称,利用这样的方法我们就在类的外部建立了一个名为rp 的test类大成员函数(方法),可能很多人要问,这么做有意义吗?在类的内部写函数代码不是更好?答案是这样的:在类的定义中,一般成员函数的规模一般都比较小,而且一些特殊的语句是不能够使用的,而且一般会被自动的设置成为inline(内联)函数,即使你没有明确的声明为inline,那么为什么有会被自动设置成为inline呢?因为大多数情况下,类的定义一般是放在头文件中的,在编译的时候这些函数的定义也随之进入头文件,这样就会导致被多次编译,如果是inline的情况,函数定义在调用处扩展,就避免了重复编译的问题,而且把大量的成员函数都放在类中使用起来也十分不方便,为了避免这种情况的发生,所以c++是允许在外部定义类的成员函数(方法)的,将类定义和其它成员函数定义分开,是面向对象编程的通常做法,我们把类的定义在这里也就是头文件了看作是类的外部接口,类的成员函数的定义看成是类的内部实现。

软件设计模式六大原则

软件设计模式六大原则

软件设计模式六⼤原则⽬录:设计模式六⼤原则(1):单⼀职责原则定义:不要存在多于⼀个导致类变更的原因。

通俗的说,即⼀个类只负责⼀项职责。

问题由来:类T负责两个不同的职责:职责P1,职责P2。

当由于职责P1需求发⽣改变⽽需要修改类T时,有可能会导致原本运⾏正常的职责P2功能发⽣故障。

解决⽅案:遵循单⼀职责原则。

分别建⽴两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。

这样,当修改类T1时,不会使职责P2发⽣故障风险;同理,当修改T2时,也不会使职责P1发⽣故障风险。

说到单⼀职责原则,很多⼈都会不屑⼀顾。

因为它太简单了。

稍有经验的程序员即使从来没有读过设计模式、从来没有听说过单⼀职责原则,在设计软件时也会⾃觉的遵守这⼀重要原则,因为这是常识。

在软件编程中,谁也不希望因为修改了⼀个功能导致其他的功能发⽣故障。

⽽避免出现这⼀问题的⽅法便是遵循单⼀职责原则。

虽然单⼀职责原则如此简单,并且被认为是常识,但是即便是经验丰富的程序员写出的程序,也会有违背这⼀原则的代码存在。

为什么会出现这种现象呢?因为有职责扩散。

所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。

⽐如:类T只负责⼀个职责P,这样设计是符合单⼀职责原则的。

后来由于某种原因,也许是需求变更了,也许是程序的设计者境界提⾼了,需要将职责P细分为粒度更细的职责P1,P2,这时如果要使程序遵循单⼀职责原则,需要将类T也分解为两个类T1和T2,分别负责P1、P2两个职责。

但是在程序已经写好的情况下,这样做简直太费时间了。

所以,简单的修改类T,⽤它来负责两个职责是⼀个⽐较不错的选择,虽然这样做有悖于单⼀职责原则。

(这样做的风险在于职责扩散的不确定性,因为我们不会想到这个职责P,在未来可能会扩散为P1,P2,P3,P4……Pn。

所以记住,在职责扩散到我们⽆法控制的程度之前,⽴刻对代码进⾏重构。

)举例说明,⽤⼀个类描述动物呼吸这个场景:class Animal{public void breathe(String animal){System.out.println(animal+"呼吸空⽓");}}public class Client{public static void main(String[] args){Animal animal = new Animal();animal.breathe("⽜");animal.breathe("⽺");animal.breathe("猪");}}运⾏结果:⽜呼吸空⽓⽺呼吸空⽓猪呼吸空⽓程序上线后,发现问题了,并不是所有的动物都呼吸空⽓的,⽐如鱼就是呼吸⽔的。

程序设计七大原则

程序设计七大原则

软件设计的七大原则设计模式遵循的一般原则:1.开-闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开发,对修改关闭.说的是,再设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展.换言之,应当可以在不必修改源代码的情况下改变这个模块的行为,在保持系统一定稳定性的基础上,对系统进行扩展。

这是面向对象设计(OOD)的基石,也是最重要的原则。

2.里氏代换原则(Liskov Substitution Principle,常缩写为.LSP)(1).由Barbar Liskov(芭芭拉.里氏)提出,是继承复用的基石。

(2).严格表达:如果每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换称o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型.换言之,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象和子类对象的区别.只有衍生类可以替换基类,软件单位的功能才能不受影响,基类才能真正被复用,而衍生类也能够在基类的基础上增加新功能。

(3).反过来的代换不成立(4).<墨子.小取>中说:"白马,马也; 乘白马,乘马也.骊马(黑马),马也;乘骊马,乘马也."(5).该类西方著名的例程为:正方形是否是长方形的子类(答案是"否")。

类似的还有椭圆和圆的关系。

(6).应当尽量从抽象类继承,而不从具体类继承,一般而言,如果有两个具体类A,B有继承关系,那么一个最简单的修改方案是建立一个抽象类C,然后让类A和B 成为抽象类C的子类.即如果有一个由继承关系形成的登记结构的话,那么在等级结构的树形图上面所有的树叶节点都应当是具体类;而所有的树枝节点都应当是抽象类或者接口.(7)."基于契约设计(Design By Constract),简称DBC"这项技术对LISKOV代换原则提供了支持.该项技术Bertrand Meyer伯特兰做过详细的介绍:使用DBC,类的编写者显式地规定针对该类的契约.客户代码的编写者可以通过该契约获悉可以依赖的行为方式.契约是通过每个方法声明的前置条件(preconditions)和后置条件(postconditions)来指定的.要使一个方法得以执行,前置条件必须为真.执行完毕后,该方法要保证后置条件为真.就是说,在重新声明派生类中的例程(routine)时,只能使用相等或者更弱的前置条件来替换原始的前置条件,只能使用相等或者更强的后置条件来替换原始的后置条件.3.依赖倒置原则(Dependence Inversion Principle),要求客户端依赖于抽象耦合.(1)表述:抽象不应当依赖于细节,细节应当依赖于抽象.(Program to an interface, not an implementaction)(2)表述二:针对接口编程的意思是说,应当使用接口和抽象类进行变量的类型声明,参量的类型声明,方法的返还类型声明,以及数据类型的转换等.不要针对实现编程的意思就是说,不应当使用具体类进行变量的类型声明,参量类型声明,方法的返还类型声明,以及数据类型的转换等.要保证做到这一点,一个具体的类应等只实现接口和抽象类中声明过的方法,而不应当给出多余的方法.只要一个被引用的对象存在抽象类型,就应当在任何引用此对象的地方使用抽象类型,包括参量的类型声明,方法返还类型的声明,属性变量的类型声明等. (3)接口与抽象的区别就在于抽象类可以提供某些方法的部分实现,而接口则不可以,这也大概是抽象类唯一的优点.如果向一个抽象类加入一个新的具体方法,那么所有的子类型一下子就都得到得到了这个新的具体方法,而接口做不到这一点.如果向一个接口加入了一个新的方法的话,所有实现这个接口的类就全部不能通过编译了,因为它们都没有实现这个新声明的方法.这显然是接口的一个缺点.(4)一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的登记结构中,而由于一般语言都限制一个类只能从最多一个超类继承,因此将抽象作为类型定义工具的效能大打折扣.反过来,看接口,就会发现任何一个实现了一个接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个接口.(5)从代码重构的角度上讲,将一个单独的具体类重构成一个接口的实现是很容易的,只需要声明一个接口,并将重要的方法添加到接口声明中,然后在具体类定义语句中加上保留字以继承于该接口就行了.而作为一个已有的具体类添加一个抽象类作为抽象类型不那么容易,因为这个具体类有可能已经有一个超类.这样一来,这个新定义的抽象类只好继续向上移动,变成这个超类的超类,如此循环,最后这个新的抽象类必定处于整个类型等级结构的最上端,从而使登记结构中的所有成员都会受到影响.(6)接口是定义混合类型的理想工具,所为混合类型,就是在一个类的主类型之外的次要类型.一个混合类型表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为.(7)联合使用接口和抽象类:由于抽象类具有提供缺省实现的优点,而接口具有其他所有优点,所以联合使用两者就是一个很好的选择.首先,声明类型的工作仍然接口承担的,但是同时给出的还有一个抽象类,为这个接口给出一个缺省实现.其他同属于这个抽象类型的具体类可以选择实现这个接口,也可以选择继承自这个抽象类.如果一个具体类直接实现这个接口的话,它就必须自行实现所有的接口;相反,如果它继承自抽象类的话,它可以省去一些不必要的的方法,因为它可以从抽象类中自动得到这些方法的缺省实现;如果需要向接口加入一个新的方法的话,那么只要同时向这个抽象类加入这个方法的一个具体实现就可以了,因为所有继承自这个抽象类的子类都会从这个抽象类得到这个具体方法.这其实就是缺省适配器模式(Defaule Adapter).(8)什么是高层策略呢?它是应用背后的抽象,是那些不随具体细节的改变而改变的真理. 它是系统内部的系统____隐喻.4.接口隔离原则(Interface Segregation Principle, ISP) (1)一个类对另外一个类的依赖是建立在最小的接口上。

Python6大设计原则

Python6大设计原则

Python6⼤设计原则内容总览六⼤设计原则都有哪些⼀、单⼀职责原则⼆、⾥⽒替换原则三、依赖倒置原则四、接⼝隔离原则五、迪⽶特法则六、开放封闭原则内容详解⼀、单⼀职责原则单⼀职责原则:英⽂名称是Single Responsiblity Principle,简称是SRP。

定义:应该有且仅有⼀个原因引起类的变更。

单⼀职责原则要求:⼀个接⼝或类只有⼀个原因引起变化,也就是⼀个接⼝或类只有⼀个职责,它就负责⼀件事情。

单⼀职责原则的好处:1. 类的复杂性降低,实现什么职责都有清晰明确的定义;2. 可读性提⾼,复杂性降低,那当然可读性提⾼了;3. 可维护性提⾼,可读性提⾼,那当然更容易维护了;4. 变更引起的风险降低,变更是必不可少的,如果接⼝的单⼀职责做得好,⼀个接⼝修改只对相应的实现类有影响,对其他的接⼝⽆影响,这对系统的扩展性、维护性都有⾮常⼤的帮助。

注意:单⼀职责原则提出了⼀个编写程序的标准,⽤“职责”或“变化原因”来衡量接⼝或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项⽬⽽异,因环境⽽异。

对于单⼀职责原则,接⼝⼀定要做到单⼀职责,类的设计尽量做到只有⼀个原因引起变化。

⼆、⾥⽒替换原则⾥⽒替换原则(Liskov Substitution Principle,LSP),有两种定义:第⼀种定义,也是最正宗的定义:If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T ,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每⼀个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的⾏为没有发⽣变化,那么类型S是类型T的⼦类型。

面向对象设计六大原则

面向对象设计六大原则

面向对象设计六大原则面向对象设计的原则是面向对象思想的提炼,它比面向对象思想的核心要素更具可操作性,但与设计模式相比,却又更加的抽象,是设计精神要义的抽象概括。

形象地将,面向对象思想像法理的精神,设计原则则相对于基本宪法,而设计模式就好比各式各样的具体法律条文了。

面向对象设计原则有6个:开放封闭原则,单一职责原则,依赖倒置原则,Liskov替换原则,迪米特法则和接口隔离原则或合成/聚合复用原则(不同资料略有不同,这里对7个都做了整理)。

1单一职责原则(Single Responsibility Principle SRP)There should never be more than one reason for a class to change. 什么意思呢?所谓单一职责原则就是一个类只负责一个职责,只有一个引起变化的原因。

如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化会削弱或抑制这个类完成其他职责的能力,这个耦合会导致脆弱的设计。

软件设计真正要做的许多内容,就是发现职责并把这些职责相互分离;如果能够想到多于一个动机去改变一个类,那么这个类就具有多于一个职责,就应该考虑类的分离。

以调制解调器为例如下图:从上述类图里面我们发现有四个方法Dial(拨通电话),Hangup(挂电话),Receive(收到信息),Send(发送信息),经过分析不难判断出,实际上Dial(拨通电话)和Hangup(挂电话)是属于连接的范畴,而Receive(收到信息)和Send(发送信息)是属于数据传送的范畴。

这里类包括两个职责,显然违反了SRP。

这样做有潜在的隐患,如果要改变连接的方式,势必要修改Modem,而修改Modem 类的结果导致凡事依赖Modem类可能都需要修改,这样就需要重新编译和部署,不管数据传输这部分是否需要修改。

因此要重构Modem类,从中抽象出两个接口,一个专门负责连接,另一个专门负责数据传送。

23种设计模式

23种设计模式

23种设计模式(Design Patterns)设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

一、总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

还用两类模式:并发型模式和线程池模式。

二、设计模式六大原则:总原则:开闭原则开闭原则就是说对扩展开放,对修改关闭。

在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。

所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。

想要达到这样的效果,我们需要使用接口和抽象类等。

1、单一职责原则不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。

2、里氏替换原则(Liskov Substitution Principle)里氏代换原则(Liskov Substitution Principle LSP)是面向对象设计的基本原则之一。

里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。

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

里氏代换原则是对“开-闭”原则的补充。

面向对象设计七大原则

面向对象设计七大原则

⾯向对象设计七⼤原则1. 单⼀职责原则(Single Responsibility Principle)每⼀个类应该专注于做⼀件事情。

2. ⾥⽒替换原则(Liskov Substitution Principle)超类存在的地⽅,⼦类是可以替换的。

3. 依赖倒置原则(Dependence Inversion Principle)实现尽量依赖抽象,不依赖具体实现。

4. 接⼝隔离原则(Interface Segregation Principle)应当为客户端提供尽可能⼩的单独的接⼝,⽽不是提供⼤的总的接⼝。

5. 迪⽶特法则(Law Of Demeter)⼜叫最少知识原则,⼀个软件实体应当尽可能少的与其他实体发⽣相互作⽤。

6. 开闭原则(Open Close Principle)⾯向扩展开放,⾯向修改关闭。

7. 组合/聚合复⽤原则(Composite/Aggregate Reuse Principle CARP)尽量使⽤合成/聚合达到复⽤,尽量少⽤继承。

原则:⼀个类中有另⼀个类的对象。

细则单⼀职责原则(Single Responsibility Principle)因为:可以降低类的复杂度,⼀个类只负责⼀项职责,其逻辑肯定要⽐负责多项职责简单的多;提⾼类的可读性,提⾼系统的可维护性;变更引起的风险降低,变更是必然的,如果单⼀职责原则遵守的好,当修改⼀个功能时,可以显著降低对其他功能的影响。

需要说明的⼀点是单⼀职责原则不只是⾯向对象编程思想所特有的,只要是模块化的程序设计,都适⽤单⼀职责原则。

所以:从⼤局上看Android中的Paint和Canvas等类都遵守单⼀职责原则,Paint和Canvas各司其职。

⾥⽒替换原则(Liskov Substitution Principle)因为:⾥⽒替换原则告诉我们,在软件中将⼀个基类对象替换成它的⼦类对象,程序将不会产⽣任何错误和异常,反过来则不成⽴,如果⼀个软件实体使⽤的是⼀个⼦类对象的话,那么它不⼀定能够使⽤基类对象。

设计模式的例子

设计模式的例子

开闭原则开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。

import ng.*;interface Fruit{public void plant();public void blossom();public void outcome();}class Apple implements Fruit{Apple(){this.plant();}public void plant(){System.out.println("Plant a apple");};public void blossom(){System.out.println("Apple blossomed");};public void outcome(){System.out.println("Apple outcomed");};}class Pear implements Fruit{Pear(){this.plant();}public void plant(){System.out.println("Pear a apple");};public void blossom(){System.out.println("Pear blossomed");};public void outcome(){System.out.println("Pear outcomed");};}interface gardenerBase //Garden,是不能改变的.以后增加一个水果只需要再写个类继承它!{public Fruit getFruit();}class AppleGardener implements gardenerBase//种植Apple的Garden{private static AppleGardener singleton;private AppleGardener(){;}public static AppleGardener getGardener(){if(singleton==null)singleton = new AppleGardener();return singleton;}public Fruit getFruit(){return new Apple();}}class PearGardener implements gardenerBase//种植Pear的Garden{private static PearGardener singleton;private PearGardener(){;}public static PearGardener getGardener(){if(singleton==null)singleton = new PearGardener();return singleton;}public Fruit getFruit(){return new Pear();}}public class MyFirstOCPJA VA{public static void main(String []a){Fruit tempApple;gardenerBase appleGarden = AppleGardener.getGardener();tempApple = appleGarden.getFruit();Fruit tempPear;gardenerBase pearGarden = PearGardener.getGardener();tempPear = pearGarden.getFruit();}}里氏代换原则一个软件实体如果使用的是一个基类的话,那么一定适用于其子类。

软件工程中里氏设计原则与马克思主义

软件工程中里氏设计原则与马克思主义

软件工程中里氏替换原则与马克思主义钱星月软件工程与马克思主义在谈及里氏原则如何印证马克思主义之前,我想先谈一下软件工程与马克思主义的联系。

软件工程是一门从实践发展出来的学科,与计算机科学分别代表了计算机领域的理论与实践部分。

程序设计出现的30年后,生产力的发展和“软件危机”的产生使计算机行业产生了新的保障程序质量的需求,催生出了软件工程这一专业。

从它的实践的初衷来看,软件工程的内核跟马克思主义有着千丝万缕的关系,其很多实践的理论都多方面地印证了马克思主义的正确性。

里氏替换原则可以说是这门学科中最具特色也最具代表性的一项理论。

它是以面向对象编程技术为基础,发展出来的一套程序设计规范。

它深刻地印证了马克思主义的矛盾普遍性和特殊性以及个性与共性的辩证方法。

面向对象编程方法该从里氏原则的基础,面向对象编程(Object Oriented Programming)讲起。

所谓面向对象编程,包含了两个方面。

第一,它基于对象的编程思想。

即将相关的繁多数据抽象成一个对象(将信息打包封装),通过对这一个对象的不同操作来操作数据。

比如一位交大学生小明的信息,包括姓名、学号、班级以及各门课程的成绩,通过基于对象的方法,只需创建一个叫小明的对象,便可访问小明的这些信息。

不同于传统的编程思想,此过程大大的简化了数据处理过程的代码。

它的产生便是主体客体化和客体主体化的一个体现:通过实践,从数据客体创造出对象客体,同时这一成果也影响着程序员编程的思路。

第二,它融入了多态的概念。

即通过一定的设计,使用户能通过同一个方法来对不同的对象进行操作。

举个例子,当你想向一个不会中文的美国人或一个不会英文的中国人问好,你需要分别使用“Hello !”和“你好!”,但在多态的思想中,你只需要使用“问好”这一行为便能达到这个目的。

这里需要引入基类和子类的概念。

基类往往是较为抽象的,而子类往往是较为具体的。

以人类为例:假使基类是人类,则子类可以是小学生、成年女性、退休老人。

设计7大原则

设计7大原则

• 在开闭原则的定义中,软件实体可以指一个软件模 块、一个由多个类组成的局部结构或一个独立的类。
• 类抽象化是开闭原则的关键。
• 开闭原则还可以通过一个更加具体的“对可变性封 装原则”来描述,对可变性封装原则(Principle of Encapsulation of Variation, EVP)要求找到系统的 可变因素并将其封装起来。
合成复用原则定义
合成复用原则(Composite Reuse Principle, CRP)又称为组合 /聚合复用原则(Composition/ Aggregate Reuse Principle, CARP),其定义如下:
尽量使用对象组合,而不是继承来达到复用的目的。
• 合成复用原则就是指在一个新的对象里通过关联关系(包括组合关 系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分; 新对象通过委派调用已有对象的方法达到复用其已有功能的目的。 简言之:要尽量使用组合/聚合关系,少用继承。
高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象 不应该依赖于细节,细节应该依赖于抽象。
• 另一种定义
要针对接口编程,不要针对实现编程。
• 简单来说,依赖倒转原则就是指:代码要依赖于抽 象的类,而不要依赖于具体的类;要针对接口或抽 象类编程,而不是针对具体类编程。
• 实现开闭原则的关键是抽象化,并且从抽象化导出 具体化实现,如果说开闭原则是面向对象设计的目 标的话,那么依赖倒转原则就是面向对象设计的主 要手段。
• 需求说明
• 由于需求的变化,该系统可能需要增加新的数据源 或者新的文件格式,每增加一个新类型的数据源或 者新类型的文件格式,客户类MainClass都需要修改 源代码,以便使用新的类,但违背了开闭原则。现 使用依赖倒转原则对其进行重构。

设计模式六大原则(PHP)

设计模式六大原则(PHP)

设计模式六⼤原则(PHP)设计模式的⽬的是为了更好的代码重⽤性,可读性,可靠性和可维护性。

常⽤的六⼤设计模式有:单⼀职责原则(SRP),⾥⽒替换原则(LSP),依赖倒转原则(DIP),接⼝隔离原则(ISP),迪⽶特法则(LOD),开闭原则(OCP)。

1.单⼀职责原则(Single Responsibility Principle)该原则是针对类来说的,即⼀个类应该只负责⼀项职责。

假设有⼀个部门的类叫做T,他的下⾯有两个职责的⽅法叫做P1,P2。

假如P1的职责发⽣改变时去修改这个部门类T,那么有可能造成职责P2发⽣故障。

举个栗⼦:我们⽤动物呼吸的场景来表现⼀下输出结果:但是呢,我们发现并不是所有的动物都是呼吸空⽓的,⽐如说鱼它是呼吸⽔的。

根据SRP原则,我们应该将Animal类分为陆地动物和海洋⽣物,如下所⽰:但是我们发现这样修改花销很⼤,既要将原来的类分解,⼜要修改客户端。

⽽直接修改Animal类则违背了单⼀职责原则,但花销很⼩如下所⽰:这种修改⽅式没有改变原来的⽅法,⽽是在类中新加了⼀个⽅法,这样虽然违反了单⼀职责原则,但是在⽅法级别上却是符合单⼀职责原则的。

在实际的编程中,只有逻辑⾜够简单,才可能在代码级违反单⼀职责原则;只有类中的⽅法数量⾜够少,才可以在⽅法级别上违反单⼀职责原则。

遵循单⼀职责的优点:(1)降低类的复杂度,⼀个类只负责⼀项职责。

(2)提⾼类的可读性,可维护性。

(1)降低变更引起的风险。

2.⾥⽒替换原则(Liskov Substitution Principle)该原则提出,如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的⾏为没有发⽣变化,那么类型T2是类型T1的⼦类型。

这话原句,不知道是翻译的锅还是咋地,看起来就晦涩难懂。

其实可以简单地理解为所有引⽤基类的地⽅必须能够透明的使⽤其⼦类的对象,在⼦类中尽量不要重写和重载⽗类的⽅法。

面向对象编程的五大原则

面向对象编程的五大原则

面向对象编程的五大原则单一职责原则开放封闭原则里氏替换原则依赖倒置原则接口隔离原则高层的实现不应该依赖底层,(父类可以替换掉任何子类),具体说就是我们要针对接口抽象来编程,不要针对实现来编程,这样程序才能解耦。

一、"开-闭"原则(Open-Closed Principle,OCP)1.1"开-闭"原则的定义及优点1)定义:一个软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification.)。

即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。

2)满足"开-闭"原则的系统的优点a)通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性。

b)已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化中的软件系统有一定的稳定性和延续性。

c)这样的系统同时满足了可复用性与可维护性。

1.2如何实现"开-闭"原则在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。

换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。

解决问题关键在于抽象化,抽象化是面向对象设计的第一个核心本质。

对一个事物抽象化,实质上是在概括归纳总结它的本质。

抽象让我们抓住最最重要的东西,从更高一层去思考。

这降低了思考的复杂度,我们不用同时考虑那么多的东西。

换言之,我们封装了事物的本质,看不到任何细节。

在面向对象编程中,通过抽象类及接口,规定了具体类的特征作为抽象层,相对稳定,不需更改,从而满足"对修改关闭";而从抽象类导出的具体类可以改变系统的行为,从而满足"对扩展开放"。

对实体进行扩展时,不必改动软件的源代码或者二进制代码。

面向对象的设计原则四资料

面向对象的设计原则四资料

面向对象的设计原则四 - 里氏代换原则动机当我们设计程序模块时,我们会创建一些类层次结构,然后我们通过扩展一些类来创建它们的子类。

我们必须确保子类只是扩展而没有替换父类的功能,否则当我们在已有程序模块中使用它们时将会产生不可预料的结果。

里氏代换原则表明当一个程序模块使用基类时,基类的引用可以被子类替换而不影响模块的功能。

里氏代换原则基类完全能够被子类替代而不影响模块的功能。

实例对于多态来说里氏代换原则好像是很显然的事情,例如:Java代码1. public void drawShape(Shape s) {2. // Code here.3. }对于Shape的任何子类来说,drawShape方法都应该能很好的工作。

我们必须小心的实现子类以免无意中违反了里氏代换原则,如果一个函数不满足里氏代换原则,那么它可能必须显式地引用子类对象,这样的函数同样违反了开闭原则,因为当添加新的子类时,必须修改它。

考虑下面的矩形类:Java代码1. // A very nice Rectangle class.2. public class Rectangle {3. private double width;4. private double height;5. public Rectangle(double w, double h) {6. width = w;7. height = h;8. }9. public double getWidth() {return width;}10. public double getHeight() {return height;}11. public void setWidth(double w) {width = w;}12. public void setHeight(double h) {height = h;}13. public double area() {return (width * height);14.}现在,如果有个正方形呢?显然正方形是一个矩形,所以我们应该让正方形继承矩形类,是这样吗?我们看一下!注意:正方形不需要同时具有宽和高属性,但是它还是从矩形继承了这些属性。

面向对象七大原则

面向对象七大原则

一、☆面向对象的七大原则:1) 开闭原则;---- 面向扩展开放,面向修改关闭。

2) 里氏转换原则;---- 超类存在的地方,子类是可以替换的。

3) 依赖倒转原则;---- 实现尽量依赖抽象,不依赖具体实现。

4) 接口隔离原则;---- 应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口。

5) 组合/聚合复用原则;尽量使用合成/聚合达到复用,尽量少用继承。

原则:一个类中有另一个类的对象。

6) “迪米特”法则;----- 又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。

7) 单一职责原则。

---- 每一个类应该专注于做一件事情。

二、开闭原则OCP:开闭原则是设计原则基础的基础,是java 面向对象的核心原则,其它原则均围绕开闭原则进行展开。

开闭原则指的是一个软件实体应对对扩展开放,对修改关闭(Software entities should be open for extension, but closed for modification) 。

这个原则是说在设计一个模块的时候,应对使这个模块可以在不被修改的前提下被扩展,换言之,应对可以不必修改源代码的情况下改变这个模块的行为。

☆ 满足开闭原则的软件系统的优越性:① 通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性。

② 已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化中的软件系统有一定的稳定性和延续性。

☆实现开闭原则的关键抽象化是解决问题的关键,在面向对象的编程语言里,可以给系统定义出一套相对较为固定的抽象设计,此设计允许无穷无尽的行为在实现层被实现。

在语言里,可以给出个或多个抽象类或者接口,规定出所有的具体类必须提供的方法的特征作为系统设计的抽象层。

这个抽象层预见了所有的可扩展性,因此,在任何扩展情况下都不会改变。

这就使得系统的抽象不需要修改,从而满足了开闭原则的第二条,对修改关闭。

设计模式(Design Patterns)可复用面向对象软件的基础

设计模式(Design Patterns)可复用面向对象软件的基础

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

本章系Java之美[从菜鸟到高手演变]系列之设计模式,我们会以理论与实践相结合的方式来进行本章的学习,希望广大程序爱好者,学好设计模式,做一个优秀的软件工程师!一、设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

其实还有两类:并发型模式和线程池模式。

用一个图片来整体描述一下:二、设计模式的六大原则1、开闭原则(Open Close Principle)开闭原则就是说对扩展开放,对修改关闭。

在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。

所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。

想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。

里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。

应用程序系统基本设计原则——SOLID

应用程序系统基本设计原则——SOLID

应⽤程序系统基本设计原则——SOLID应⽤系统设计应该遵循⼀些的设计的基本原则,其实这些思想也是源于GOF的设计模式的总结,在创建⼀个低成本,⾼可⽤、⾼扩展性、低耦⾼内聚的应⽤程序,我们需要遵循的⼀套规范性的东西,简称SOLID,SOLID由可分为以下⼏点:1、S ingle Responsibility Principle(单⼀职责原则)2、O pen Close Principle(开-闭原则)3、L iskov Substitution Principle(⾥⽒代换原则)4、I nterface Segregation Principle(接⼝分离原则)5、D ependency Inversion Principle(依赖反转原则)简单介绍这⼏个原则:1、单⼀职责原则:每个类应该只有⼀个独⼀⽆⼆的职责,或者说每个类只能有⼀个主要功能,每个类应该尽可能少的依赖其他类,这也体现了封装的概念。

2、开-闭原则:每个类,应该对“扩展”进⾏开放,⽽对“修改”进⾏封闭,也就是⽀持扩展,⽽不是⽀持修改,当然完全符合这个原则稍微有点难度,确切的说是保证最⼩限度的修改代码来实现系统的功能扩展,⽐如:继承、设计模式中的⼏个创建型模式都是在尽量的解决此问题,⽽不是通过修改既有代码。

3、⾥⽒替换原则:⼦类型必须能够替换掉他们的⽗类型。

在⼀个软件实体如果使⽤的是⼀个⽗类的话,那么⼀定适合于其⼦类,⽽且他观察不出⽗类对象和⼦类对象的区别,也就是说,在软件⾥⾯,把⽗类都替换成它的⼦类,程序⾏为没有变化。

4、接⼝分离原则:接⼝的职责也应该是单⼀的,接⼝中应该包含哪些⽅法,需要进⾏严格的评估,如果其中某些⽅法的职责于接⼝的本⾝定义不相符合,则应该将其分离到其他接⼝中。

类需要根据其调⽤所需要的不同接⼝类型,来暴露不同的接⼝,同样也是类单⼀职责的体现。

5、依赖反转原则:也叫依赖倒置原则,抽象不能依赖于具体,⽽具体则应该依赖抽象。

六大设计原则

六大设计原则

六⼤设计原则六⼤设计原则1. 单⼀职责原则:对于⼀个类,应该只有⼀个引起它变化的原因;【功能内聚】2. ⾥⽒代换原则:⼦类必须能够替换掉它们的⽗类型;【减⼩继承耦合】3. 开放-封闭原则:对于扩展是开放的;对于修改是封闭的。

4. 依赖倒置原则:程序的⾼层模块不应该依赖于底层模块,两者应依赖于抽象;抽象不应该依赖于具体斜街,⽽细节应该依赖于抽象。

【⾯向接⼝编程,⽽不是针对实现编程】【耦合具有⽅向性差异,稳定与变化之间的耦合,接⼝稳定⽽具体易变化】5. 合成/聚合复⽤原则:尽量不使⽤类继承,⽽尽量使⽤合成/聚合【避免类爆炸】6. 迪⽶特法则:如果两个类之间不必直接通信,则这个类不应该发⽣直接相互作⽤。

如果其中⼀个类需要调⽤另⼀个类的某个⽅法,可以通过第三⽅转发这个调⽤。

【体现在顺序图中,跨“朋友/友元”调⽤“陌⽣”对象,进⾏改进】⼀、单⼀职责原则举例:超⼈只维护世界原因:易于维护和⾼度的可复⽤性是⾯向对象开发的⽐较突出的两个优点。

若职责过于庞⼤,则维护困难,可复⽤性也随之降低,与⾯向对象的思想背道⽽驰。

好处:降低类的复杂度,⼀个类只负责⼀项职责,其逻辑肯定⽐负责多项职责简单;提⾼类的可读性,提⾼系统的可维护性。

⼆、⾥⽒代换原则举例:超⼈只维护世界符合:鲨鱼是鱼,⽼⽊匠徒弟替⽼⽊匠打家具;违反:正⽅形是长⽅形【如何修改,构造⼀个抽象的四边形类】作⽤:使得使⽤⽗类类型的模块在⽆需修改的情况下,就可以通过使⽤不同的⼦类拓展。

⾥⽒代换规则是对实现抽象化的具体步骤的规范。

【⾥⽒代换原则是对开闭原则的进⼀步规范】三、开放-封闭原则(OCP)----⾯向对象设计的主要⽬标原因:封装变化、降低耦合效果:开闭原则提供了⼀个使系统在⾯对需求变更时,可以保持系统相对稳定的解决⽅案。

举例:符合:动物-猫-咪咪(继承/多态复⽤,并拓展)对⽐:1. 银⾏业务员(存款、取款、转账、进⾏基⾦申购)2. 银⾏业务员接⼝,存款业务员、取款业务员、负责转账业务员、基⾦业务员//其实这⾥的改写也体现了单⼀职责原则,依赖于抽象的银⾏业务员接⼝利于扩展核⼼思想:只依赖于抽象,⾯向抽象编程,⽽不是⾯向具体编程。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

如果有一个方法“骑马()”
如果有一个方法qm(m a)的话: 如果有一个方法qm(m a)的话: qm(m a)
一匹白马 一匹黑马
这就是里氏代换原则:如果对每个类型T1的对象o1, 这就是里氏代换原则:如果对每个类型T1的对象o1, 都有类型为T2的对象O2,使得一T1定义的所有 都有类型为T2的对象O2,使得一T1定义的所有 程序P在所有对象o1都代换成o2时,程序P 程序P在所有对象o1都代换成o2时,程序P的行 为没有变化,那么T2为T1的子类型。 为没有变化,那么T2为T1的子类型。
课前热身讲解
Class A{} Clas B extends A { void aa(A a) { System.out.println(“打印”); System.out.println(“打印”); } } Class c { public static void main(String args[]) { A aa=new A(); B bb=new B(); bb.aa(aa); bb.aa(bb); }
import java.util.*; class Aa { public static void main(String args[]) { Vector A=new Vector(); String s="Hello"; A.add(s); String m="World !"; aAdd(A,m); } static void aAdd(Vector K,String n) { K.add(n); K.trimToSize(); System.out.print(K.toString()); }
墨子“取譬“----再说里氏代换原则
白马与马
《墨子-小取》中说,“白马,马也,乘白马, 乘马也。骊马-“白马”-“一匹白马” 马”- 白马”“马”是抽象的马, 而白马和黑马是马 的具体子类。一匹 白马则是“白马” 白马则是“白马” 类的实例;一匹黑 马则是“黑马” 马则是“黑马”类 的实例。如果一个 方法适用于马,那 么必然适用于白马 或黑马。
相关文档
最新文档