您的位置:首页 > 其它

设计模式(内容是我从书上总结下来的,分享给大家)

2016-09-08 14:52 387 查看
前言:设计模式是一种程序设计理想化的状态,开发时应该尽可能遵循这些模式,这和开发者思想、水平还有对业务思考有关,切记不可因为达不到预期的理想模式而迟迟不去编码,开发模式只是一种手段而非绝对,这种手段只是便于程序后期的维护拓展而已。

(目前有28种设计模式)

面对对象基础:

抽象类:

1. 把实例化没有任何意义的父类,改成抽象类

2. 抽象类不能实例化;抽象方法是必须被子类重写的方法;类中包含抽象方法,那么类就必须定义为抽象类

3. 抽象类是用来继承的,具体类不是用来继承的,作为编程开发者应该努力做到这一点,如下图:



接口:

1.接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合。一旦类实现了接口,类就可以支持接口所指定的所有属性和成员。声明接口在语法上与声明抽象类完全相同,但不允许提供接口中任何成员的执行方式。

2. 接口的命名,前面要加一个大写字母 I ,这是规范

3. 接口中的方法或属性前面不能有修饰符、方法没有方法体(接口类前面可以有修饰符)

抽象类和接口区别:

表象的形态来讨论:抽象类可以给出一些成员的实现,接口却不包含成员的实现,抽象类的抽象成员可被子类部分实现,接口的成员徐亚哟偶实现类完全实现,一个类只能继承一个抽象类,但可实现多个接口等

补充理解:

1. 类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象。

(接口是对类的局部(行为)进行的抽象,而抽象类是对类整体(字段、属性、方法)的抽象。如果只关注行为抽象,那么也可以认为接口就是抽象类)

2. 如果行为跨越不同类的对象,可使用接口;对于一些相似的类对象,可继承抽象类

3. 从设计角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本不知道子类的存在,方法是如何实现还不确认,预先定义。

(抽象类往往都是通过重构得来的,当然,如果你事先意识到多种分类的可能,那么事先就设计出抽象类也是完全可以的。抽象类是自底而上抽象出来的,而接口则是自顶而下设计出来的)

第1章:代码无错便是优

1. 考虑通过封装、继承、多态把程序的耦合度降低,达到的效果就是:可维护(修改)、可复用(重用)、可拓展(添加)、灵活性好(排序)

2. 编程有一原则,就是用尽可能的办法去避免重复,可行做法就是让业务逻辑与界面逻辑分开

3. 尽量避免添加或删减功能使得原来运行良好的功能代码发生改变的风险

4. 工厂模式:用一个单独的类来做创造实例的过程(根据传入的标识自动创造不同实例的过程)

另外补充:

聚合:是一种弱的‘拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。例如:雁群包含大雁,但大雁不是雁群一部分

合成(组合):是一种强的拥有关系,体现了严格的部分整体的关系,部分和整体的生命的生命周期一样。例如:鸟和翅膀的关系

以下是UML类图:



第19章:组合模式

1. 组合模式:将对象组合成树形结构以表示部分—整体的层次结构,并使得用户对单个对象和组合对象的使用具有一致性(考虑使用该模式)

2. 透明方式(一致):所有子类具备相同的接口方法,所有子类对外具备完全一致的行为接口,但会有可能会重写没意义的方法

3. 安全方式(不一致需判断):在接口中只定义所有子类都需要的功能方法,在特殊的子类中添加特别具备的功能方法,在客户端调用需要做相关判断

总结:

设计以上的模式,最终是设计操作方式

补充:抽象类不可以直接实例化,但可以写构造方法,子类需要实现这个构造方法

第3章:单一职责原则

单一职责原则:就一个类而言,应该仅有一个引起它变化的原因(反过来说,多于一个动机去改变一个类)

什么时候需要职责分离:软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离,其实要去判断是否应该分离出类,也不难,那就是如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离。

第4章:开放–封闭原则

1. 两个特征:对拓展是开放的,对修改是封闭的。设计软件要容易维护又不容易出问题最好的办法就是多拓展,少修改。

2. 无论模块是多么封闭,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最优可能发生的变化种类,然后构造抽象来隔离那些变化。

(在发生很小变化时立即采取抽象行动,在我们最初编写代码时,假设变化不会发生,当发生时,我们就创建抽象类隔离以后发生的同类变化)

3. 开放封闭原则是面向对象设计的核心所在,遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可拓展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都可以地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。

第2章:策略模式

1. 面向对象编程,就是善于发现相同的规律,并抽象出来类

2. 客户端让客户接触的操作类越少越好,客户端尽可能的作为控制的中心,把其他代码尽可能的转移出去,让客户端简洁

3. 策略模式封装变化,封装变化点是面对对象的一种很重要的思维方式

4. 策略就是可以用相同的方法调用所需对象的方法,这些方法和对象实例化统一在策略类中进行处理,这里一般是策略+工厂模式配合使用

(之所以能调用所有方法是使用到java多态的特性,父类调用子类方法)

5. 任何需要的变更都是需要成本的,高手就是做同样的事花最小的代价



第5章:依赖倒转原则

依赖倒转原则:

1. 高层模块不应该依赖底层模块,两个都应该依赖抽象(抽象类或接口)

2. 抽象不应该依赖细节,细节应该依赖抽象

里氏代换原则:

子类型必须能够替换掉它们的父类型

补充:

1. 子类拥有父类所有的非private的行为和属性

2. 父类是所有子类共有属性的抽象体

3. 只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。

4. 依赖倒转其实可以说是面向对象编程的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对接口编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。

第21章:单例模式

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点(单例的有个基本问题)

(确保全局唯一访问点:所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,默认的构造方法就会失效)

多线程单例:处理方法是双重锁定,既保证单例又不浪费性能


第9章:原型模式

原型模式:就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。(另一个可定制的对象应该包括浅复制和深复制)

1. 传引用,一个对象实例,可以理解为浅复制

Resume a = new Resume():

Resume b = a;

2. 字段内容全部复制过去,两个对象实例,可以理解为深复制

Resume a = new Resume():

Resume b = new Resume():

b = a ;

补充:

1. string是一种拥有值类型特点的特殊引用类型

第6章:装饰模式

装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

理解:通过共有的接口或抽象类,在作为装饰的子类中使用重写和复用手段,动态为父类对象添加额外功能。这种写法和写子类的写法差不多,只是在装饰的过程中比直接写子类的动态添加装饰来的稍微灵活点。

注意:装饰模式在装饰的过程中需要不断的把上一个对象装饰完毕后的状态交给下一个装饰对象来继续装饰,这样才会有装饰不断增加的效果。



第8章:工厂方法模式

1. 工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。

2. 工厂方法符合开放封闭原则,需要新功能拓展子类即可,工厂类中不修改,但需要在客户端判断修改。(简单工厂中判断逻辑在工厂,新增需要修改工厂类)

2. 简单工厂模式和工厂方法对比



第16章:状态模式

状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

好处:将与特定状态相关的行为局部化,并且将不同状态的行为分割开来

使用场景:当一个对状态决定它的行为,就可以考虑状态模式

补充:

1. 方法过长是坏味道,面向对象设计其实就是希望做到代码的责任分解

2. 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要使用状态模式了,根据实际情况具体分析处理。







第17章:适配器模式

适配器模式:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适用场景:

1. 使用一个已存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑适配器模式。

2. 在接口双方都不容易改动的情况下才考虑适配器模式,可以改动的应该优先考虑重构统一接口。

补充:

1. 需要的东西就在面前,但却不能适用,而短时间又无法改造它,于是我们就想办法适它。这模式对早期代码复用一些功能很有实用价值。

2. 如果能事前控制,又何必要事后再去弥补





第23章:命令模式

命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

敏捷开发原则:不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式(其他模式一样),一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如“撤销、恢复”操作等功能时,把原来的代码重构为命令模式才有意义。







第25章:中介者模式

中介者模式(调停者模式):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

优点:

1. 安理会(中介者)的出现减少了各个国家的耦合,使得可以独立地改变和复用中介者和各个国家类。

2. 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。

缺点:由于安理会控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得安理会(中介者)会变比任何一个国家类都复杂。

适用场景:中介者模式一般应用于一组对象以定义良好但复杂的方式进行通信的场合。

注意:中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了“多对多”交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统在设计上是不是合理。







第27章:解释器模式

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

1. 正则表达式就是解释器的一种应用(正则原理,搜索算法)

2. 适用场景:当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式

3. 解释器好处:该模式使用类来表示文法,可使用继承来改变或拓展文法,容易改变和拓展。

4. 解释器不足:解释器为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术手段,如语法分析程序或编译器生产器来处理。

以上是我在看大话设计模式的书自个记录的,分享给大家,希望对大家对程序的有不同的思考。

大家遇到企业开发中的问题,可以微信搜索:技术帮团队,IT领域的问题专家,可以及时解答疑问。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐