从七月份开始一直到九月底才看完设计模式,在这个过程当中我不敢说我已经掌握了那本书里面的内容,或者说1/5,没能力说也没有资格说。可是结果不重要,重要的是这个过程个人收获!主要包括以下几个方面:html
一、认识了这么多设计模式。刚刚接触java没多久就在学长那里听过设计模式的大名,可是因为能力有限,一直不敢触碰。而今有幸将其都认识了。java
二、开始有设计的理论了。在接触设计模式以前没有怎么想过设计方面东东,看到问题就立马动手解决,没有想到怎么样来设计更好,如何来是这块更加优化、漂亮。算法
三、开始考虑系统的可扩展性了。编程
四、在遇到问题后开始想有那个设计模式会适用这个场景。设计模式
五、对面向对象有了更深一步的了解。数据结构
鄙人天资不聪慧,既不是聪明人,更不是那种天才,全部顿悟有限!!!闲话过多,先看以下两幅图片架构
设计模式之间的关系:函数
设计模式总概况:优化
一个类,只有一个引发它变化的缘由。应该只有一个职责。每个职责都是变化的一个轴线,若是一个类有一个以上的职责,这些职责就耦合在了一块儿。这会致使脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一块儿,会影响复用性。例如:要实现逻辑和界面的分离。from:百度百科ui
开闭原则就是说对扩展开放,对修改关闭。在程序须要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。因此一句话归纳就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,咱们须要使用接口和抽象类,后面的具体设计中咱们会提到这点。
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类能够出现的地方,子类必定能够出现。 LSP是继承复用的基石,只有当衍生类能够替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也可以在基类的基础上增长新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,因此里氏代换原则是对实现抽象化的具体步骤的规范。from:百度百科
所谓依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就下降了客户与实现模块间的耦合。
实现开闭原则的关键是抽象化,而且从抽象化导出具体化实现,若是说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。 from:百度百科
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。仍是一个下降类之间的耦合度的意思,从这儿咱们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。因此上文中屡次出现:下降依赖,下降耦合。
合成复用原则就是指在一个新的对象里经过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象经过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽可能使用组合/聚合关系,少用继承。
为何叫最少知道原则,就是说:一个实体应当尽可能少的与其余实体之间发生相互做用,使得系统功能模块相对独立。也就是说一个软件实体应当尽量少的与其余实体发生相互做用。这样,当一个模块修改时,就会尽可能少的影响其余的模块,扩展会相对容易,这是对软件实体之间通讯的限制,它要求限制软件实体之间通讯的宽度和深度。
在软件工程中,建立型模式是处理对象建立的设计模式,试图根据实际状况使用合适的方式建立对象。基本的对象建立方式可能会致使设计上的问题,或增长设计的复杂度。建立型模式经过以某种方式控制对象的建立来解决问题。
建立型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例建立和结合的方式。
建立型模式又分为对象建立型模式和类建立型模式。对象建立型模式处理对象的建立,类建立型模式处理类的建立。详细地说,对象建立型模式把对象建立的一部分推迟到另外一个对象中,而类建立型模式将它对象的建立推迟到子类中。
所谓抽象工厂模式就是她提供一个接口,用于建立相关或者依赖对象的家族,而不须要明确指定具体类。他容许客户端使用抽象的接口来建立一组相关的产品,而不须要关系实际产出的具体产品是什么。这样一来,客户就能够从具体的产品中被解耦。它的优势是隔离了具体类的生成,使得客户端不须要知道什么被建立了,而缺点就在于新增新的行为会比较麻烦,由于当添加一个新的产品对象时,须要更加须要更改接口及其下全部子类。其UML结构图以下:
参与者:
AbstractFactory:抽象工厂。抽象工厂定义了一个接口,全部的具体工厂都必须实现此接口,这个接口包含了一组方法用来生产产品。
ConcreteFactory:具体工厂。具体工厂是用于生产不一样产品族。要建立一个产品,客户只须要使用其中一个工厂彻底不须要实例化任何产品对象。
AbstractProduct:抽象产品。这是一个产品家族,每个具体工厂都可以生产一整组产品。
Product:具体产品。
对于建造者模式而已,它主要是将一个复杂对象的构建与表示分离,使得一样的构建过程能够建立不一样的表示。适用于那些产品对象的内部结构比较复杂。
建造者模式将复杂产品的构建过程封装分解在不一样的方法中,使得建立过程很是清晰,可以让咱们更加精确的控制复杂产品对象的建立过程,同时它隔离了复杂产品对象的建立和使用,使得相同的建立过程可以建立不一样的产品。可是若是某个产品的内部结构过于复杂,将会致使整个系统变得很是庞大,不利于控制,同时若几个产品之间存在较大的差别,则不适用建造者模式,毕竟这个世界上存在相同点大的两个产品并非不少,因此它的使用范围有限。其UML结构图:
Builder:抽象建造者。它声明为建立一个Product对象的各个部件指定的抽象接口。
ConcreteBuilder:具体建造者。实现抽象接口,构建和装配各个部件。
Director:指挥者。构建一个使用Builder接口的对象。它主要是用于建立一个复杂的对象,它主要有两个做用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
Product:产品角色。一个具体的产品对象。
做为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个建立对象的接口,但由子类决定要实例化的类是哪个,也就是说工厂方法模式让实例化推迟到子类。
工厂方法模式很是符合“开闭原则”,当须要增长一个新的产品时,咱们只须要增长一个具体的产品类和与之对应的具体工厂便可,无须修改原有系统。同时在工厂方法模式中用户只须要知道生产产品的具体工厂便可,无须关系产品的建立过程,甚至连具体的产品类名称都不须要知道。虽然他很好的符合了“开闭原则”,可是因为每新增一个新产品时就须要增长两个类,这样势必会致使系统的复杂度增长。其UML结构图:
参与者:
Product:抽象产品。全部的产品必须实现这个共同的接口,这样一来,使用这些产品的类既能够引用这个接口。而不是具体类 。
ConcreteProduct:具体产品。
Creator:抽象工厂。它实现了全部操纵产品的方法,但不实现工厂方法。Creator全部的子类都必需要实现factoryMethod()方法。
ConcreteCreator:具体工厂。制造产品的实际工厂。它负责建立一个或者多个具体产品,只有ConcreteCreator类知道如何建立这些产品。
在咱们应用程序可能有某些对象的结构比较复杂,可是咱们又须要频繁的使用它们,若是这个时候咱们来不断的新建这个对象势必会大大损耗系统内存的,这个时候咱们须要使用原型模式来对这个结构复杂又要频繁使用的对象进行克隆。因此原型模式就是用原型实例指定建立对象的种类,而且经过复制这些原型建立新的对象。
它主要应用与那些建立新对象的成本过大时。它的主要优势就是简化了新对象的建立过程,提升了效率,同时原型模式提供了简化的建立结构。UML结构图:
参与者:
Prototype:抽象原型类。声明克隆自身的接口。
ConcretePrototype:具体原型类。实现克隆的具体操做。
Client:客户类。让一个原型克隆自身,从而得到一个新的对象。
单例模式,从字面上看就是一个实例的意思。因此它的定义就是确保某一个类只有一个实例,而且提供一个全局访问点。
单例模式具有以下几个特色:
一、只有一个实例。
二、可以自我实例化。
三、提供全局访问点。
因此说当系统中只须要一个实例对象或者系统中只容许一个公共访问点,除了这个公共访问点外,不能经过其余访问点访问该实例时,可使用单例模式。
单例模式的主要优势就是节约系统资源、提升了系统效率,同时也可以严格控制客户对它的访问。也许就是由于系统中只有一个实例,这样就致使了单例类的职责太重,违背了“单一职责原则”,同时也没有抽象类,因此扩展起来有必定的困难。其UML结构图很是简单,就只有一个类:
参与者:
Singleton:单例。
结构型模式主要是用于处理类或者对象的组合,它描述了如何来类或者对象更好的组合起来,是从程序的结构上来解决模块之间的耦合问题。它主要包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式这个七个模式。
在咱们的应用程序中咱们可能须要将两个不一样接口的类来进行通讯,在不修改这两个的前提下咱们可能会须要某个中间件来完成这个衔接的过程。这个中间件就是适配器。所谓适配器模式就是将一个类的接口,转换成客户指望的另外一个接口。它可让本来两个不兼容的接口可以无缝完成对接。
做为中间件的适配器将目标类和适配者解耦,增长了类的透明性和可复用性。
参与者:
Target:目标抽象类 。
Adapter:适配器类 。经过在内部包装一个Adaptee,将源接口转成目标接口。
Adaptee:适配者类 。须要适配的类。
Client:客户类。
若是说某个系统可以从多个角度来进行分类,且每一种分类均可能会变化,那么咱们须要作的就是讲这多个角度分离出来,使得他们能独立变化,减小他们之间的耦合,这个分离过程就使用了桥接模式。所谓桥接模式就是讲抽象部分和实现部分隔离开来,使得他们可以独立变化。
桥接模式将继承关系转化成关联关系,封装了变化,完成了解耦,减小了系统中类的数量,也减小了代码量。
参与者
Abstraction:抽象类。
RefinedAbstraction:扩充抽象类。
Implementor:实现类接口。
ConcreteImplementor:具体实现类 。
组合模式组合多个对象造成树形结构以表示“总体-部分”的结构层次。它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程当中无须进行区分,能够对他们进行一致的处理。
在使用组合模式中须要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式可以将叶子节点和对象节点进行一致处理的缘由。
虽然组合模式可以清晰地定义分层次的复杂对象,也使得增长新构件也更容易,可是这样就致使了系统的设计变得更加抽象,若是系统的业务规则比较复杂的话,使用组合模式就有必定的挑战了。
参与者:
Component :组合中的对象声明接口,在适当的状况下,实现全部类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
Leaf:叶子对象。叶子结点没有子结点。
Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操做,如增长(add)和删除(remove)等。
咱们能够经过继承和组合的方式来给一个对象添加行为,虽然使用继承可以很好拥有父类的行为,可是它存在几个缺陷:1、对象之间的关系复杂的话,系统变得复杂不利于维护。2、容易产生“类爆炸”现象。3、是静态的。在这里咱们能够经过使用装饰者模式来解决这个问题。
装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。虽然装饰者模式可以动态将责任附加到对象上,可是他会产生许多的细小对象,增长了系统的复杂度。
参与者:
Component: 抽象构件。是定义一个对象接口,能够给这些对象动态地添加职责。
ConcreteComponent:具体构件。是定义了一个具体的对象,也能够给这个对象添加一些职责。
Decorator: 抽象装饰类。是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来讲,是无需知道Decorator存在的。
ConcreteDecorator:具体装饰类,起到给Component添加职责的功能。
咱们都知道类与类之间的耦合越低,那么可复用性就越好,若是两个类没必要彼此通讯,那么就不要让这两个类发生直接的相互关系,若是须要调用里面的方法,能够经过第三者来转发调用。外观模式很是好的诠释了这段话。外观模式提供了一个统一的接口,用来访问子系统中的一群接口。它让一个应用程序中子系统间的相互依赖关系减小到了最少,它给子系统提供了一个简单、单一的屏障,客户经过这个屏障来与子系统进行通讯。
经过使用外观模式,使得客户对子系统的引用变得简单了,实现了客户与子系统之间的松耦合。可是它违背了“开闭原则”,由于增长新的子系统可能须要修改外观类或客户端的源代码。
参与者:
Facade: 外观角色。知道哪些子系统类负责处理请求,将客户的请求代理给适合的子系统处理。
SubSystem:子系统角色。实现子系统功能,处理Facade对象发来的请求。
在一个系统中对象会使得内存占用过多,特别是那些大量重复的对象,这就是对系统资源的极大浪费。享元模式对对象的重用提供了一种解决方案,它使用共享技术对相同或者类似对象实现重用。
享元模式就是运行共享技术有效地支持大量细粒度对象的复用。系统使用少许对象,并且这些都比较类似,状态变化小,能够实现对象的屡次复用。这里有一点要注意:享元模式要求可以共享的对象必须是细粒度对象。
享元模式经过共享技术使得系统中的对象个数大大减小了,同时享元模式使用了内部状态和外部状态,同时外部状态相对独立,不会影响到内部状态,因此享元模式可以使得享元对象在不一样的环境下被共享。同时正是分为了内部状态和外部状态,享元模式会使得系统变得更加复杂,同时也会致使读取外部状态所消耗的时间过长。
参与者:
Flyweight: 抽象享元类。全部具体享元类的超类或者接口,经过这个接口,Flyweight能够接受并做用于外部专题。
ConcreteFlyweight: 具体享元类。指定内部状态,为内部状态增长存储空间。
UnsharedConcreteFlyweight: 非共享具体享元类。指出那些不须要共享的Flyweight子类。
FlyweightFactory: 享元工厂类。用来建立并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经建立的Flyweight对象或者新建一个(若是不存在)。
代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不能直接与真正的目标对象通讯。代理对象是目标对象的表明,其余须要与这个目标对象打交道的操做都是和这个代理对象在交涉。
代理对象能够在客户端和目标对象之间起到中介的做用,这样起到了的做用和保护了目标对象的,同时也在必定程度上面减小了系统的耦合度。
参与者:
Subject: 抽象角色。声明真实对象和代理对象的共同接口。
Proxy: 代理角色。代理对象与真实对象实现相同的接口,因此它可以在任什么时候刻都可以代理真实对象。代理角色内部包含有对真实对象的引用,因此她能够操做真实对象,同时也能够附加其余的操做,至关于对真实对象进行封装。
RealSubject: 真实角色。它表明着真实对象,是咱们最终要引用的对象。
行为型模式主要是用于描述类或者对象是怎样交互和怎样分配职责的。它涉及到算法和对象间的职责分配,不只描述对象或者类的模式,还描述了他们之间的通讯方式,它将你的注意力从控制流转移到了对象间的关系上来。行为型类模式采用继承机制在类间分派行为,而行为型对象模式使用对象复合而不是继承。它主要包括如何11中设计模式:职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式。
职责链模式描述的请求如何沿着对象所组成的链来传递的。它将对象组成一条链,发送者将请求发给链的第一个接收者,而且沿着这条链传递,直到有一个对象来处理它或者直到最后也没有对象处理而留在链末尾端。
避免请求发送者与接收者耦合在一块儿,让多个对象都有可能接收请求,将这些对象链接成一条链,而且沿着这条链传递请求,直到有对象处理它为止,这就是职责链模式。在职责链模式中,使得每个对象都有可能来处理请求,从而实现了请求的发送者和接收者之间的解耦。同时职责链模式简化了对象的结构,它使得每一个对象都只须要引用它的后继者便可,而没必要了解整条链,这样既提升了系统的灵活性也使得增长新的请求处理类也比较方便。可是在职责链中咱们不能保证全部的请求都可以被处理,并且不利于观察运行时特征。
参与者:
Handler: 抽象处理者。定义了一个处理请求的方法。全部的处理者都必须实现该抽象类。
ConcreteHandler: 具体处理者。处理它所负责的请求,同时也能够访问它的后继者。若是它可以处理该请求则处理,不然将请求传递到它的后继者。
Client: 客户类。
有些时候咱们想某个对象发送一个请求,可是咱们并不知道该请求的具体接收者是谁,具体的处理过程是如何的,们只知道在程序运行中指定具体的请求接收者便可,对于这样将请求封装成对象的咱们称之为命令模式。因此命令模式将请求封装成对象,以便使用不一样的请求、队列或者日志来参数化其余对象。同时命令模式支持可撤销的操做。
命令模式能够将请求的发送者和接收者之间实现彻底的解耦,发送者和接收者之间没有直接的联系,发送者只须要知道如何发送请求命令便可,其他的能够一律无论,甚至命令是否成功都无需关心。同时咱们能够很是方便的增长新的命令,可是可能就是由于方便和对请求的封装就会致使系统中会存在过多的具体命令类。
Command: 抽象命令类。用来声明执行操做的接口。
ConcreteCommand: 具体命令类。将一个接收者对象绑定于一个动做,调用接收者相应的操做,以实现Excute。
Invoker: 调用者。要求该命令执行这个请求。
Receiver: 接收者。知道如何实施与执行一个请求相关的操做,任何类都有可能成为一个接收者。
Client:客户类。
所谓解释器模式就是定义语言的文法,而且创建一个解释器来解释该语言中的句子。解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。
参与者:
AbstractExpression: 抽象表达式。声明一个抽象的解释操做,该接口为抽象语法树中全部的节点共享。
TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操做。实现抽象表达式中所要求的方法。文法中每个终结符都有一个具体的终结表达式与之相对应。
NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操做。
Context: 环境类。包含解释器以外的一些全局信息。
Client: 客户类。
对于迭代在编程过程当中咱们常常用到,可以游走于聚合内的每个元素,同时还能够提供多种不一样的遍历方式,这就是迭代器模式的设计动机。在咱们实际的开发过程当中,咱们可能会须要根据不一样的需求以不一样的方式来遍历整个对象,可是咱们又不但愿在聚合对象的抽象接口中充斥着各类不一样的遍历操做,因而咱们就但愿有某个东西可以以多种不一样的方式来遍历一个聚合对象,这时迭代器模式出现了。
何为迭代器模式?所谓迭代器模式就是提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示。迭代器模式是将迭代元素的责任交给迭代器,而不是聚合对象,咱们甚至在不须要知道该聚合对象的内部结构就能够实现该聚合对象的迭代。
经过迭代器模式,使得聚合对象的结构更加简单,它不须要关注它元素的遍历,只须要专一它应该专一的事情,这样就更加符合单一职责原则了。
Iterator: 抽象迭代器:全部迭代器都须要实现的接口,提供了游走聚合对象元素之间的方法。
ConcreteIterator: 具体迭代器。利用这个具体的迭代器可以对具体的聚合对象进行遍历。每个聚合对象都应该对应一个具体的迭代器。
Aggregate: 抽象聚合类。
ConcreteAggregate: 具体聚合类。实现creatorIterator()方法,返回该聚合对象的迭代器。
租房各位都有过的经历吧!在这个过程当中中介结构扮演着很重要的角色,它在这里起到一个中间者的做用,给咱们和房主互相传递信息。在外面软件的世界里一样须要这样一个中间者。在咱们的系统中有时候会存在着对象与对象之间存在着很强、复杂的关联关系,若是让他们之间有直接的联系的话,一定会致使整个系统变得很是复杂,并且可扩展性不好!在前面咱们就知道若是两个类之间没有没必要彼此通讯,咱们就不该该让他们有直接的关联关系,若是实在是须要通讯的话,咱们能够经过第三者来转发他们的请求。一样,这里咱们利用中介者来解决这个问题。
所谓中介者模式就是用一个中介对象来封装一系列的对象交互,中介者使各对象不须要显式地相互引用,从而使其耦合松散,并且能够独立地改变它们之间的交互。在中介者模式中,中介对象用来封装对象之间的关系,各个对象能够不须要知道具体的信息经过中介者对象就能够实现相互通讯。它减小了对象之间的互相关系,提供了系统可复用性,简化了系统的结构。
在中介者模式中,各个对象不须要互相知道了解,他们只须要知道中介者对象便可,可是中介者对象就必需要知道全部的对象和他们之间的关联关系,正是由于这样就致使了中介者对象的结构过于复杂,承担了过多的职责,同时它也是整个系统的核心所在,它有问题将会致使整个系统的问题。因此若是在系统的设计过程当中若是出现“多对多”的复杂关系群时,千万别急着使用中介者模式,而是要仔细思考是否是您设计的系统存在问题。
参与者:
Mediator: 抽象中介者。定义了同事对象到中介者对象之间的接口。
ConcreteMediator: 具体中介者。实现抽象中介者的方法,它须要知道全部的具体同事类,同时须要从具体的同事类那里接收信息,而且向具体的同事类发送信息。
Colleague: 抽象同事类。
ConcreteColleague: 具体同事类。每一个具体同事类都只须要知道本身的行为便可,可是他们都须要认识中介者。
后悔药人人都想要,可是事实倒是残酷的,根本就没有后悔药可买,可是也不只如此,在软件的世界里就有后悔药!备忘录模式就是一种后悔药,它给咱们的软件提供后悔药的机制,经过它可使系统恢复到某一特定的历史状态。
所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态,这样能够在之后将对象恢复到原先保存的状态。它实现了对信息的封装,使得客户不须要关心状态保存的细节。保存就要消耗资源,因此备忘录模式的缺点就在于消耗资源。若是类的成员变量过多,势必会占用比较大的资源,并且每一次保存都会消耗必定的内存。
参与者:
Originator: 原发器。负责建立一个备忘录,用以记录当前对象的内部状态,经过也可使用它来利用备忘录恢复内部状态。同时原发器还能够根据须要决定Memento存储Originator的那些内部状态。
Memento: 备忘录。用于存储Originator的内部状态,而且能够防止Originator之外的对象访问Memento。在备忘录Memento中有两个接口,其中Caretaker只能看到备忘录中的窄接口,它只能将备忘录传递给其余对象。Originator能够看到宽接口,容许它访问返回到先前状态的全部数据。
Caretaker: 负责人。负责保存好备忘录,不能对备忘录的内容进行操做和访问,只可以将备忘录传递给其余对象。
何谓观察者模式?观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的全部依赖者都会收到通知而且自动更新。
在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标能够对应多个观察者,并且这些观察者之间没有相互联系,因此么能够根据须要增长和删除观察者,使得系统更易于扩展。
因此观察者提供了一种对象设计,让主题和观察者之间以松耦合的方式结合。
参与者:
Subject:目标。他把全部对观察者对戏的引用保存在一个汇集里,每个主题均可以有多个观察者。
Observer:观察者。为全部的具体观察者定义一个接口,在获得主题的通知时可以及时的更新本身。
ConcreteSubject:具体主题。将有关状态存入具体观察者对象。在具体主题发生改变时,给全部的观察者发出通知。
ConcreteObserver:具体观察者。实现抽象观察者角色所要求的更新接口,以便使自己的状态与主题状态相协调。
在不少状况下咱们对象的行为依赖于它的一个或者多个变化的属性,这些可变的属性咱们称之为状态,也就是说行为依赖状态,即当该对象由于在外部的互动而致使他的状态发生变化,从而它的行为也会作出相应的变化。对于这种状况,咱们是不能用行为来控制状态的变化,而应该站在状态的角度来思考行为,便是什么状态就要作出什么样的行为。这个就是状态模式。
因此状态模式就是容许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
在状态模式中咱们能够减小大块的if…else语句,它是容许态转换逻辑与状态对象合成一体,可是减小if…else语句的代价就是会换来大量的类,因此状态模式势必会增长系统中类或者对象的个数。
同时状态模式是将全部与某个状态有关的行为放到一个类中,而且能够方便地增长新的状态,只须要改变对象状态便可改变对象的行为。可是这样就会致使系统的结构和实现都会比较复杂,若是使用不当就会致使程序的结构和代码混乱,不利于维护。
参与者:
Context:环境类。能够包括一些内部状态。
State: 抽象状态类。State定义了一个全部具体状态的共同接口,任何状态都实现这个相同的接口,这样一来,状态之间就能够互相转换了。
ConcreteState:具体状态类。具体状态类,用于处理来自Context的请求,每个ConcreteState都提供了它对本身请求的实现,因此,当Context改变状态时行为也会跟着改变。
咱们知道一件事可能会有不少种方式来实现它,可是其中总有一种最高效的方式,在软件开发的世界里面一样如此,咱们也有不少中方法来实现一个功能,可是咱们须要一种简单、高效的方式来实现它,使得系统可以很是灵活,这就是策略模式。
因此策略模式就是定义了算法族,分别封装起来,让他们以前能够互相转换,此模式然该算法的变化独立于使用算法的客户。
在策略模式中它将这些解决问题的方法定义成一个算法群,每个方法都对应着一个具体的算法,这里的一个算法我就称之为一个策略。虽然策略模式定义了算法,可是它并不提供算法的选择,即什么算法对于什么问题最合适这是策略模式所不关心的,因此对于策略的选择仍是要客户端来作。客户必需要清楚的知道每一个算法之间的区别和在何时什么地方使用什么策略是最合适的,这样就增长客户端的负担。
同时策略模式也很是完美的符合了“开闭原则”,用户能够在不修改原有系统的基础上选择算法或行为,也能够灵活地增长新的算法或行为。可是一个策略对应一个类将会是系统产生不少的策略类。
参与者:
Context: 环境类。维护一个Strategy对象的引用,用一个ConcreteStrategy来配置,可定义一个接口来让Strategy访问它的数据。
Strategy: 抽象策略类。定义全部支持算法的公共接口。Context使用这个接口来调用某个Concretestrategy定义的算法。
ConcreteStrategy: 具体策略类。封装了具体的算法实现。
有些时候咱们作某几件事情的步骤都差很少,仅有那么一小点的不一样,在软件开发的世界里一样如此,若是咱们都将这些步骤都一一作的话,费时费力不讨好。因此咱们能够将这些步骤分解、封装起来,而后利用继承的方式来继承便可,固然不一样的能够本身重写实现嘛!这就是模板方法模式提供的解决方案。
所谓模板方法模式就是在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类能够在不改变算法结构的状况下,从新定义算法中的某些步骤。
模板方法模式就是基于继承的代码复用技术的。在模板方法模式中,咱们能够将相同部分的代码放在父类中,而将不一样的代码放入不一样的子类中。也就是说咱们须要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数的形式实现,而后声明一些抽象方法让子类来实现剩余的逻辑,不一样的子类能够以不一样的方式来实现这些逻辑。因此模板方法的模板其实就是一个普通的方法,只不过这个方法是将算法实现的步骤封装起来的。
参与者:
AbstractClass: 抽象类。实现了一个模板,实现算法的基本骨架,具体子类将重定义primitiveOperation()方法以实现一个算法步骤。
ConcreteClass: 具体子类。实现primitiveOperation()方法以完成算法中与特定子类相关的步骤。
访问者模式俗称23大设计模式中最难的一个。除告终构复杂外,理解也比较难。在咱们软件开发中咱们可能会对同一个对象有不一样的处理,若是咱们都作分别的处理,将会产生灾难性的错误。对于这种问题,访问者模式提供了比较好的解决方案。
访问者模式即表示一个做用于某对象结构中的各元素的操做,它使咱们能够在不改变各元素的类的前提下定义做用于这些元素的新操做。
访问者模式的目的是封装一些施加于某种数据结构元素之上的操做,一旦这些操做须要修改的话,接受这个操做的数据结构能够保持不变。为不一样类型的元素提供多种访问操做方式,且能够在不修改原有系统的状况下增长新的操做方式。同时咱们还须要明确一点那就是访问者模式是适用于那些数据结构比较稳定的,由于他是将数据的操做与数据结构进行分离了,若是某个系统的数据结构相对稳定,可是操做算法易于变化的话,就比较适用适用访问者模式,由于访问者模式使得算法操做的增长变得比较简单了。
参与者:
Vistor: 抽象访问者。为该对象结构中的ConcreteElement的每个类声明的一个操做。
ConcreteVisitor: 具体访问者。实现Visitor申明的每个操做,每个操做实现算法的一部分。
Element: 抽象元素。定义一个Accept操做,它以一个访问者为参数。
ConcreteElement: 具体元素 。实现Accept操做。
ObjectStructure: 对象结构。可以枚举它的元素,能够提供一个高层的接口来容许访问者访问它的元素。
上面只是对各个设计模式的一个简单的总结,下面我将列出详情,各位看客有兴趣的能够点点:
感谢Eric Freeman , Elisabeth Freeman , Kathy Sierra & Bert Bates所编写的《Head First design patterns》,正是这本书将我领入设计模式的大门,虽然只是刚刚跨过门槛,但早已陶醉于那浓浓的、醇正的知识香中。还要感谢刘伟老师的PPT,您的教程给了我一个很好的参考。
虽然看完了设计模式,但这并非结束,而是刚刚开始,在之后的项目过程当中,我会尽可能去优化,思考。
诚然,最近在作项目的过程当中深感基础不够扎实,因此下一步就是java基础了:think in java ,I must conquer you!!!!
博文有点儿长,感谢各位看客可以看完,若是以为不错,请推荐个吧!!!!