设计模式--前言

设计模式的概念:

设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的优秀代码设计经验的总结。使用设计模式是为了提高代码的重用性,是代码更易理解并保证代码的可靠性。

这就是为什么之前用框架时有好多的疑问,如果懂了设计模式,就可以去剖析框架。也是追求写好代码的程序员们的必修课。

Java设计模式贯彻的原理是:面向接口编程,而不是面向实现。其目标原则是:降低耦合,增加灵活性。

设计模式的要素:

1.模式名称(pattern name)

  设计模式的名称简洁的描述了设计模式的问题、解决方案和效果。

2.问题(problem)

  问题描述了应该在何时使用模式。它解释了实际问题和问题存在的前因后果。

3.环境或初始环境(context或initial context)

  环境说明模式的使用范围,也是模式应用之前的起始条件。(也叫前提条件)

4.解决方案(solution)

  解决方案描述了设计的组成部分,以及他们之间的相互关系及各自的职责和写作方式。模式就是一个模板,可应用于多种不同场合,因此解决方案并不描述一个特定二具体的设计或实现。

5.效果(consequences)

  效果描述了模式应用和使用模式应权衡的问题。效果用来描述设计模式的利弊,它往往是衡量模式是否可用的重要因素。

6.举例(举例)

  通常举例使用一个或多个示意性的应用来说明特定的真实环境,并说明模式如何应用到环境中、改变环境并且给出当模式结束时的末态环境。

7.末态环境(resulting context)

  末态环境是模式应用到系统之后的状态。末态环境是模式的末态条件和可能有的副作用。她包括模式带来的好结果和坏结果。

8.推理(rationale)

  推理解释模式的步骤、规则,以及此模式作为一个整体是如何以特定的方式解决模式的。推理让使用者知道模式是如何工作的,为什么可以工作,以及使用此模式的有点是什么。

9.其他有关模式(related pattern)

  与他有关模式描述在现有的系统中某种模式与其他模式的静态和动态的关系。

10.已知应用(known uses)

  已知应用是指在一用的系统中出现或应用的模式例子,它有助于证明此模式确实是对一个重复发生的问题的可行性解答。

设计模式的原则:

用程序的复用可以提高应用程序的开发效率和质量,节约开发成本,恰当的复用还可以改善系统的可维护性。而在面向对象的设计里面,可维护性复用都是以面向对象设计原则为基础的,这些设计原则首先都是复用的原则,遵循这些设计原则可以有效地提高系统的复用性,同时提高系统的可维护性。 面向对象设计原则和设计模式也是对系统进行合理重构的指导方针。

 

1)单一职责原则(Single Responsibility Principle,SRP):类的职责要单一,不能将太多的职责放在一个类中。(高内聚、低耦合)

原则分析:
1、一个类(或者大到模块,小到方法)承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。 
2、类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
3、单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。 

优点:
1、降低类的复杂性,类的职责清晰明确。比如数据职责和行为职责清晰明确。
2、提高类的可读性和维护性,
3、变更引起的风险减低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
注意:单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否合理,但是“职责”和“变化原因”都是没有具体标准的,一个类到底要负责那些职责?这些职责怎么细化?细化后是否都要有一个接口或类?这些都需从实际的情况考虑。因项目而异,因环境而异。

2)开闭原则( Open - ClosedPrinciple ,OCP ):对扩展开放,对修改关闭

1、当软件实体因需求要变化时, 尽量通过扩展已有软件实体,可以提供新的行为,以满足对软件的新的需求,而不是修改已有的代码,使变化中的软件有一定的适应性和灵活性 。已有软件模块,特别是最重要的抽象层模块不能再修改,这使变化中的软件系统有一定的稳定性和延续性。

2、实现开闭原则的关键就是抽象化 :在"开-闭"原则中,不允许修改的是抽象的类或者接口,允许扩展的是具体的实现类,抽象类和接口在"开-闭"原则中扮演着极其重要的角色..即要预知可能变化的需求.又预见所有可能已知的扩展..所以在这里"抽象化"是关键!

3、可变性的封闭原则:找到系统的可变因素,将它封装起来. 这是对"开-闭"原则最好的实现. 不要把你的可变因素放在多个类中,或者散落在程序的各个角落. 你应该将可变的因素,封套起来..并且切忌不要把所用的可变因素封套在一起. 最好的解决办法是,分块封套你的可变因素!避免超大类,超长类,超长方法的出现!!给你的程序增加艺术气息,将程序艺术化是我们的目标!
3)里氏代换原则( Liskov Substitution Principle ,LSP ):任何基类可以出现的地方,子类也可以出现

原则分析:
1、讲的是基类和子类的关系,只有这种关系存在时,里氏代换原则才存在。正方形是长方形是理解里氏代换原则的经典例子。
2、里氏代换原则可以通俗表述为:在软件中如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。
3、里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

优缺点:
在面向对象的语言中,继承是必不可少的、非常优秀的语言机制,它有如下优点:
1、代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
2、提高代码的重用性;
3、子类可以形似父类,但又异于父类,“龙生龙,凤生凤,老鼠生来会打洞”是说子拥有父的“种”,“世界上没有两片完全相同的叶子”是指明子与父的不同;
4、提高代码的可扩展性,实现父类的方法就可以“为所欲为”了,君不见很多开源框架的扩展接口都是通过继承父类来完成的;
5、提高产品或项目的开放性。
 
自然界的所有事物都是优点和缺点并存的,即使是鸡蛋,有时候也能挑出骨头来,继承的缺点如下:
1、继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
2、降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束;
3、增强了耦合性。当父类的常量、变量和方法被修改时,必需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大片的代码需要重构。

设计模式分类

通常的设计模式可以概括为23种,按照特点可以将其分为三大类型:创建型、结构型、行为型。

创建型

创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其他关联对象的创建、组合和表示方式。所有的创建型模式都有两个主要功能:

  1.将系统所使用的具体类的信息封装起来

  2.隐藏类的实例是如何被创建和组织的。外界对于这些对象只知道他们共同的接口,而不清楚其具体的实现细节。

正因为以上两点,创建型模式在创建什么(what)、由谁来创建(who)、以及何时创建(when)这些方面,都为设计者提供了尽可能大的灵活性。

创建型模式的作用可以概括为:A.封装创建逻辑,不仅仅是new一个对象那么简单。B.封装创建逻辑变化,客户代码尽量不改变和尽量少修改。

创建型模式有以下几种:

  单例模式(Singleton Pattern):一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

  工厂方法模式(Factory Pattern):在工厂方法模式中,工厂类成为了抽象类,实际的创建工作将由其具体子类来完成。工厂的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中,它强调的是“单个对象”的变化。

  抽象工厂模式(Abstract Factory):抽象工厂是所有工厂模式中最为抽象且最具有一般性的一种形态。抽象工厂可以向客户提供一个接口,是的客户可以在没有指定产品的情况下,创建多个产品族中的产品对象,强调的是“对象系列”的变化。

  建造者模式(Builder Pattern):把构造对象实例的逻辑移到了类的内部,在类的外部定义了该类的构造逻辑。它把一个复杂对象的构造过程从对象的表示中分离出来,其直接效果是将一个复杂的对象简化为一个比较简单的目标对象,强调的是产品的构造过程。

  原型模式(Prototype Pattern):原型模式和工厂模式一样,同样对客户隐藏了对象创建工作具体的实现细节,但与通过对一个类进行实例化的构造心对象不同的是,原型模式通过复制一个现有的对象生成新对象。

其中工厂模式(Factory Pattern)属于类创建型,其他的则是对象创建型。区别在与一个类创建型使用继承改变被实例化的类,而对象创建型模式将实例化委托给另一个对象。

结构型

  结构型模式讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象实现新的功能(对象结构型模式)。这些结构型模式在某些方面具有很大的相似性,但侧重点各有不同。适配器(Adapter)是类结构型,其他的则为对象结构型模式。

  代理模式(Proxy):为其他对象提供一种代理以控制对该对象的访问。

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

  适配器模式(Adapter):将一个类的接口变换成客户端所期待的接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

  组合模式(Composite):也叫合成模式,将对象组合成属性结构一表示“部分-整体”的层次结构,使得用户对单个对象和组成对象的使用具有一致性。

  桥梁模式(Bridge):也叫桥接模式,将抽象和实现解耦,是的两者可以独立的变化。

  外观模式(Facade):也叫门面模式,要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统更易于使用。

  亨元模式(Flyweight):是池技术的重要实现方式,使用共享对象可有效的支持大量的细粒度的对象。

行为型

  行为型设计模式关注的是对象的行为,用来解决对象之间的联系问题。行为类模式使用继承机制在类间分派行为(Interpreter、Template Method)。除Interpreter、Template Method都是行为对象型使用的复合而不是继承。

  模板方法模式(Template Method):定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以在不改变算法的结构的情况下重新定义该算法的某些特定步骤。

  命令模式(Command):是一种高内聚的模式,讲一个请求封装成一个对象,从而使用不同的请求吧客户端参数化。对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

  责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,直到有对象处理它为止。

  策略模式(Strategy):也叫政策模式,定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。

  迭代器模式(Iterator):提供一种方法访问一个容器对象中的各个元素,而又不需要暴露该对象的内部细节。

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

  观察者模式(Observer):也叫发布订阅模式,定义对象间的一对多的依赖关系,是的每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

  备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保持这个状态。

  访问者模式(Visitor):封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

  状态模式(State):当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类型,状态模式的核心是封装,状态的变更会引起行为的变更。

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

猜你喜欢

转载自www.cnblogs.com/hhxz/p/10791369.html