设计模式

更新时间:2023-12-17 11:04:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1 设计模式 类 创建型 结构型 行为型 Factory Method Adapter_Class Interpreter Template Method 对象 Abstract Factory Adapter_Object Chain of Responsibility Builder Bridge Command Prototype Composite Iterator Singleton Decorator Mediator Facade Memento Flyweight Observer Proxy State Strategy Visitor 创建模式,结构模式,行为模式 1.1 ok简单工厂模式simple factory ? ? ? 又叫静态工厂方法,是由一个工厂对象决定创建出哪一种产品类的实例。 角色:工厂类、抽象产品、具体产品 退化的简单工厂模式 ? ? ? ? ? ? 如果只有一个具体产品角色的话,可以省略掉抽象产品角色 工厂角色可以由抽象产品角色扮演 ? 优点: 简单工厂模式实现了对责任的分割,客户端只管消费,工厂只管创建。客户端完全不需要知道返回的对象是怎么样创建的. 缺点: ? 新添加产品类必然导致工厂类的修改 ? ? ? ? 有限程度上支持开闭原则(要求一个系统的设计能够允许系统在无需修改的情况下扩展其功能) 当具体的产品类有不同的接口种类时候.—》功能扩展较为困难 每个工厂类可以有多个的工厂方法 单例模式和多例模式是建立在简单工厂模式的基础上.而且他们要求,工厂方法具有特殊的逻辑,以便循环使用产品的实例 ? ? ? 单例模式使用了简单工厂模式?单例类使用了静态工厂方法提供自身的实例 单例模式和多例模式的共同点在于他们都禁止外界直接将之实例化 java.text.DateFormat,一个抽象产品类同时是子类的工厂 三个角色都可以合并,一个产品类就是自身的工厂 将工厂方法的返回类型设置成抽象产品类型的做法叫针对抽象编程。是依赖倒转原则的应用 1.2 ok工厂方法模式factory method

? ? ?

别名:虚拟构造子(virtual constructor)模式,多态性(polymorphic Factory)工厂模式 用意:创建一个创建产品对象的工厂接口,将实际创建工作推迟到子类中 简单工厂模式与工厂方法模式区别 ?

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态,工厂方法模式保持了简单工厂模式的优点,而且克服了他的缺点。

?

? 工厂方法模式核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。 ? 工厂方法模式退化后变得很像简单工厂模式。 角色 ? ?

抽象工厂角色 具体工厂角色

? ? ? ?

? 抽象产品角色 ? 具体产品角色 优点

? 允许系统在不修改具体工厂角色的情况下引入新的产品。

工厂方法返还的应当是抽象类型,而不是具体类型。这有这样才能保证产品的多态性。 举例

? Collection接口的Iterator就是一个工厂方法。 工厂方法模式和模板方法模式的关系

? 工厂方法模式,经常和模版方法模式一起联合使用. ?

模版方法本身也可能就是工厂方法模式

1.3 ok抽象工厂模式Abstract factory

? ?

用意:抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族的产品对象。 抽象工厂模式与工厂方法模式最大的区别在于:

? 工厂方法模式针对的是一个产品等级结构,抽象工厂模式则需要面对多个产品等级

结构. ?

一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。显然,这时候抽象工厂模式比工厂方法模式更有效率。 ? 抽象工厂模式是工厂方法模式的进一步推广 涉及的角色

? 抽象工厂角色 ? ? ? ?

具体工厂类角色 抽象产品角色 具体产品角色

?

?

以下情况应当考虑使用抽象工厂模式 ?

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。这对于所有形态的工厂都是重要的。

? ? ? ?

这个系统的产品有多于一个的产品族。而系统只消费其中某一族的产品。(这是抽象工厂模式的原始用意。)

同属于同一个产品族的产品是在一起使用的。这一约束必须在系统设计中体现出来。

系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于

实现。

对开闭原则的支持 ? ?

在系统的产品族增加时,抽象工厂模式支持开闭原则

对于产品等级结构的增加,抽象工厂模式不支持开闭原则

1.4 ok单例模式singleton

? 单例模式确保某个类只有一个实例。而且自行实例化并向整个系统提供这个实例。 ? 单例模式的三个要点

? 某个类只能有一个实例(单例对象持有自己的引用)

?

它必须创建这个实例

? 必须自行向整个系统提供这个实例 ? 一个最重要的特点是:构造方法是私有的. ? 分类

? ?

饿汉式

懒汉式(静态工厂方法使用了同步)

? 双重检查成例对java语言编译器不成立.???????

? 同步实际上只在成员变量第一次赋值之前才有效。在成员变量有了值之后,同步化

实际上变成了不必要的瓶颈。

?

在java编译器中,Test类的初始化与test变量赋值的顺序不可预料,如果一个线程在没有同步的条件下读取test,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成。从而造成崩溃。

很多非常聪明的人在这个成例的java版本上花费了非常多的时间,到现在为止,人们得出的结论是:一般而言,双重检查成例无法在现有的java语言编译器里面工作。 ?

使用饿汉式单例模式或者对整个静态工厂方法同步化 的懒汉式单例模式足以解决

实际工作中遇到的问题。

? 登记式单例类

? ?

登记式单例类是为了克服饿汉式、懒汉式单例类均不可继承的缺点而设计的。 由于子类必须允许父类以构造子方式调用产生实例。因此它的构造子必须是公开

?

的。这样一来,就等于允许了以这样的方式产生实例而不在父类中等级。这是登记式单例类的缺点

? 由于父类的实例必须存在,才可能有子类的实例。这在有些情况下是个浪费。 ? 使用单例模式的条件

?

在一个系统中要求一个类只有一个实例时才应当使用单例模式。

? 有状态的单例类与无状态的单例类

? 在使用了EJB,RMI,JNI技术的分散式系统中。应该避免使用有状态的单例类。 ? 在同一个JVM,2个类加载器加载同一个类,会出现2个实例。除非系统有协调机制,

不然在这种情况下,应该避免使用有状态的单例类。

? java语言中的单例模式

?

public static Runtime getRuntime() ? 在每一个java应用程序里面,都有唯一的一个Runtime对象。通过这个Runtime

对象,应用程序可以与其运行环境发生相互作用。 public static Toolkit getDefaultToolkit()

?

? 单例类使用了简单工厂模式(又称静态方法工厂模式)来提供自己的实例

1.5 ok多例模式multiton

? ?

多例模式是单例模式的自然推广。 多例模式的特点

? 多例类可有多个实例

? 多例类必须自己创建,管理自己的实例,并向外界提供自己的实例。 有上限多例模式 ? ? ? ? ? ?

一个实例数目有上限的多例类.

例如掷骰子。

上限为1时候就是单例类。单例类是多例类的特殊情况。

数量少可以用静态成员变量管理多例,数量多可以用静态的容器来管理多例。

?

无上限多例模式

? 实例数目没有上限的多例模式叫做无上限多例模式

有状态和没有状态的多例类

? 如同单例类可以分为有状态和没有状态两种,多例类也可以分为有状态和没有状态

两种。

1.6 ok建造模式builder

? ?

建造模式可以将一个产品的内部表象与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象

角色:

? 抽象建造者(如果非常肯定系统只需要一个具体建造者角色的话,可以省掉抽象建? ? ? ?

造者角色)

具体建造者

导演者(是与客户打交道的角色)

? 产品

建造者模式将产品的结构和产品的零件建造过程对客户端隐藏起来,把对建造过程进行指挥的责任和具体建造零件的责任分割开来,达到责任划分和分割的目的。 模板方法设计模式和建造模式设计模式的区别 ? ?

退化的建造模式和模板方法有相似之处。

如果系统要求发生变化,(有不同零件的生成逻辑),那么有两个选择,1,改回完全的建造模式。改造成模板方法设计模式。

?

? javamail里的Message类就是一个退化的建造模式。 什么时候用建造模式

? ?

产品有复杂的内部结构。

产品对象的属性相互依赖(有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义, 有些情况下,一个对象会有一些重要的性质,在他们没有恰当那个的值之前,对象不能作为一个完整的产品使用。(比如邮件))。 在对象创建过程中,会使用到系统中的其他一些对象。这些对象在产品对象创建过程中不易得到。

建造模式的使用使得产品的内部表象可以独立的变化。使用建造模式可以使客户端不必知道产品内部组成的细节。

? ? ?

1.7 原始模型prototype

有个原型,每次都不是new出来的是克隆出来的 这个方法用的很少.速度还不如new快呢.

1.8 ok适配器模式Adapter

? ? ? ? ?

?

也叫变压器模式 也叫包装(wraper)模式

适配器模式的用意:改变源的接口,以便与目标接口相容

把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

有两种,类的适配器模式,对象的适配器模式

? 类的适配器模式把被适配的类的API转换成了目标类的API 。Adaptee和Adapater?

是继承的关系。这决定了这个适配器模式是类的。

与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成了目标类的API。与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。Adapter和Adaptee是委派关系。决定了这个适配器模式的对象的。

?

举例

? iterator与enumeration的适配

? Jdbc/odbc桥,就是适配器模式的具体应用. 与装饰模式的关系

? 装饰类不能改变他所装饰的对象的接口

?

1.9 ok缺省适配模式Default Adapter

缺省适配器模式为一个接口提供缺省实现,这样子类可以从这个缺省实现来继承,而不必从原有接口来进行扩展。

适配器模式的用意是要改变源的接口,以便与目标类的接口相容。缺省适配器的用意稍有不

? 和装饰模式的关系

1.18 ok模版方法模式

准备一个抽象类,将部分逻辑以具体方法及具体构造方法的形式实现,然后声明一些抽象方法,来迫使子类实现剩余的逻辑,不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模版方法方式的用意 模板方法是基于继承的代码复用的基本技术。 代表具体逻辑步骤的方法称作基本方法。

而将这些基本方法汇总起来的方法叫模板方法。 此模式鼓励恰当的使用继承

HttpServlet类的service方法,典型的模版方法模式

模板方法模式中的基本方法都是留给子类实现的。他们的名字应该以do开始。

1.19 ok观察者模式Observer

又叫发布-订阅模式、模型-视图模式、源-监听器模式、从属者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化的时候,会通知所有观察者对象,使他们自动更新自己.

Java1.1以后,awt事件处理机制,建立在观察者模式基础上的.因此,观察者模式在java语言中的地位较为重要。 有两种实现方式。第二种方式与第一种方式的区别:代表存储观察者对象的聚集连线是从抽象主题到抽象观察者。

第二种方案与java语言给出的对观察者模式的支持完全一致。 java.util.Observer

java.util.Observable

被观察者类都是java.util.Observable的子类 底层事件和语义事件 语义事件:ActionEvent(单击按键,选择菜单项,选择列表项,在文字框中输入文字),AdjustmentEvent(调整滚动条),ItemEvent(用户在一组选择框中选择了一个,或者在列表中选择一项),TextEvent(文字框的内容有变化)

底层事件:ComponentEvent,KeyEvent,MouseEvent,FoucusEvent,WindowEvent,ContainerEvent

1.20 ok迭代子模式

? ? ? ?

迭代子模式又叫游标模式

迭代子模式可以顺序的访问一个容器中的元素而不必暴露容器的内部表象。 JCF中广泛使用迭代子来遍历容器中的元素. 角色

? 抽象迭代子角色

? 具体迭代子角色

?

? 聚集角色

? 具体聚集角色 ? 客户端

宽接口和窄接口 ? ?

宽接口:一个聚集的接口提供了可以用来修改聚集元素的方法 窄接口:一个聚集的接口没有提供可以用来修改聚集元素的方法

?

白箱聚集与外稟迭代子

? 提供宽接口的聚集叫白箱聚集 ? ? ?

由于迭代子是在聚集的结构之外的,因此这样的迭代子又叫外稟迭代子

在这种实现中,迭代子角色是一个外部类。而具体聚集角色向外界提供遍历聚集元素的接口

迭代子模式要求聚集对象必须有一个工厂方法,也就是createIterator方法,向外界提供迭代子对象的实例。

?

黑箱聚集与内稟迭代子

? 一个黑箱聚集不向外部提供遍历自己元素对象的接口。由于内稟迭代子恰好是聚集? ?

的内部类,因此,内稟迭代子对象是可以访问聚集的元素的。

同时保证聚集对象的封装和迭代子功能的实现的方案叫黑箱实现方案。

由于迭代子是在聚集的结构之内定义的,因此这样的迭代子又叫内稟迭代子

?

游标迭代子

? 由于聚集实现自己的迭代逻辑,并向外部提供适当的借口,使得迭代子可以从外部控制聚集元素的迭代过程,这样一来迭代子控制的仅仅是一个游标而已,这种迭代

子游标迭代子。

主动迭代子和被动迭代子

? 使用主动迭代子的客户端会明显调用迭代子的next()等迭代方法。在遍历过程中向?

前进行

而客户端在使用被动迭代子时,客户端并不明显的调用迭代方法,迭代子自动退经

?

?

遍历过程。 内稟与外稟

? 使用外稟迭代子的一个重要理由是它可以被几个不同的方法和对象共同享用和控? ?

制。

使用内稟迭代子的优点是不破坏聚集的封装。

AbstractList使用内稟迭代子,但同时这个类向外提供自己的遍历方法。也就是说客户端可以定义自己的外稟迭代子。

?

静态迭代子和动态迭代子。

? 静态迭代子将原聚集复制了一份。好处是安全简单。易于实现。不容易出错。短处

是对时间和内存的消耗。 ? ?

动态迭代子保持对聚集元素的引用。完整的动态迭代子不容易实现。 简化的动态迭代子。

?

fail-fast

? 当一个算法开始之后,它的运算环境发生变化。使得算法无法进行必要的调整时,这种算法就应当立即发出故障信号。这就是fail-fast的含义。 ? 是一种出项错误时的早期警报功能。 过滤迭代子

?

? ? 在扫过聚集元素的同时进行计算。以确定呈现给客户端的元素都是满足某一个过滤条件的。或者这些元素已经经过了重新的排列。 迭代子优点 ? 聚集类的设计简单,不必对外提供遍历api。 ? 一个聚集对象可以同时有几个迭代在进行中。 ? 客户端不必知道聚集的具体类型。就可以读取和遍历聚集对象。即使聚集对象的类型发生变化也不会影响客户端的遍历。 ? 迭代子缺点 ? 迭代子模式给客户端一个聚集被顺序化的错觉 ? 迭代子给出的聚集元素没有类型特征。(应用泛型可解决此问题) 聚集角色一般提供一个工厂方法,向外界提供自己的迭代子对象。 listIterator是Iterator的子接口。 迭代子模式和工厂模式的关系。 ? ? ? Iterator与listIterator ? ? Collection定义了iterator方法。AbstractList又添加了一个ListIterator方法。 Iterator与Enumeration Iterator 删除元素 不能 不能 支持fail-fast ListIterator 删除元素 增加元素 反向迭代 支持fail-fast ? Enumeration 不能 不能 不能 不支持fail-fast 1.21 ok责任连模式 ? 什么是责任链模式: ? ? ? ? ? 系统中将会存在多个有类似处理能力的对象。当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的“责任”对象,并进行处理。 责任链可能是一条直线,一个环链,或者一个数状结构的一部分。 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 说白了就是 “推卸”责任的模式,你的问题在我这里能解决我就解决,不行就把你推给另一个对象。至于到底谁解决了这个问题了呢?我管呢! 纯与不纯 ? 纯的责任链模式,规定一个具体处理者角色只能对请求作出两种动作:自己处理;传给下家。不能出现处理了一部分,把剩下的传给了下家的情况。而且请求在责任链中必须被处理,而不能出现无果而终的结局。 责任链模式的纯与不纯的区别,就像黑猫、白猫的区别一样。不要刻意的去使自己的代码来符合一个模式的公式。只要能够使代码降低耦合、提高重用,满足系统需求并能很好的适应变化就好了。正所谓:管它黑猫白猫,抓住老鼠就是好猫! ? ? 反之,则就是不纯的责任链模式。 不纯的责任链模式还算是责任链模式吗?比如一个请求被捕获后,每个具体处理者都尝试去处理它,不管结果如何都将请求再次转发。我认为这种方式的实现,算不? 算是责任链模式的一种倒不重要,重要的是我们也能从中体味到责任链模式的思? ?

想:通过将多个处理者之间建立联系,来达到请求与具体的某个处理者的解耦。 责任链模式并不创建出责任链,责任链的创建必须由系统的其他部分创建出来。 责任链模式要求在同一个时间里,命令只可以传给一个下家,而不可以传给多个下家。

?

? 角色 ? ?

抽象处理者,(通常由java抽象类或者接口来实现) 具体处理者。

AWT1.0使用了责任链模式和命令模式来处理GUI事件。

1.1版本以后,事件处理模型是建立在观察者模式的基础上,而不是建立在责任链模式基础上

论坛关键词过滤

? 例子 ? ? ?

?

适用范围:

? 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。 ? 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 ? 可处理一个请求的对象集合应被动态指定。 优点 ? ?

写成一个类不行吗?

责任链模式减低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这

?

? ?

个请求。

? 提高了灵活性,添加新的请求处理,不需要修改原来的代码 缺点

? 是责任链模式可能会带来一些额外的性能损耗,因为它要从链子开头开始遍历。

1.22 命令模式

简单,自己看就可以了.什么时候用呢?就支持一件事.undo?

把一个请求,或者一个操作封装到一个对象里面,命令模式允许系统使用不同的请求,把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和回复功能 命令模式是对命令的封装

命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象.

1.23 备忘录模式

用的并不多

1.24 状态模式

用的不是很多

1.25 访问者模式

用的不是很多

1.26 解释器模式

如果开发一种面向对象的编程语言的编译器.可以用到

1.27 ok调停者模式

? 通常,面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成。

当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点)。

?

? 当对象的数量增加时,这种直接交互会导致对象之间复杂的、混乱的引用。这

就会影响应用程序的可维护性。同时,因为对象之间的高耦合,当一个对象直接引用其他的对象时,缩小了这些对象的复用范围。

? ? 调停者模式(Mediator Pattern)推荐抽象所有对象交互的细节到一个独立的类,

这个类就是调停者,它负责这组对象之间的交互。这组对象中的 每一个对象

仍然负责提供它所具有的服务,但为了提供服务,对象之间不能直接彼此交互。两个不同对象之间的交互通过调停者(Mediator)进行路由。所 有的对象把消息发送给调停者(Mediator)。调停者(Mediator)依据应用程序的需求把消息再发送给相应的对象。

?

? 这样的设计有以下主要的优 点:

?

随着所有对象的交互行为移到一个独立的对象中,通过调停者(Mediator)的子类替换调停者(Mediator)或者改变它的功能可以很容易的改变对象之间内部的关联行为。

? ? ?

将对象的内部依赖关系移到一个单独的对象,这样会提高对象的可用性。 因为对象不需要直接引用其他的对象,所以对象可以更容易的进行单元测试。

类之间的低耦合可以使类在不影响其他类的基础上进行修改。

? 调停者模式举例

? eg1. WTO组织:它是一个协调组织,它将各贸易区自行进行的相互协调

的强耦合变成了松散合;

?

eg2. 4个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,某人担任调停者,各MM按照各自的筹码数算钱,赚了钱的从调停者这里拿,赔了钱的也付给调停者;

eg3. 租赁中介:很多人有出租房子的需求,也有不少人需要租房,租赁中介在其中担任了调停者的角色, 疏通了两者之间的复杂关系,也方便了两者。

?

1.28 开闭原则

要求一个系统的设计能够允许系统在无需修改的情况下扩展其功能

1.29 依赖倒转原则

减少对象之间的耦合有利于系统的复用

?

? 这样的设计有以下主要的优 点:

?

随着所有对象的交互行为移到一个独立的对象中,通过调停者(Mediator)的子类替换调停者(Mediator)或者改变它的功能可以很容易的改变对象之间内部的关联行为。

? ? ?

将对象的内部依赖关系移到一个单独的对象,这样会提高对象的可用性。 因为对象不需要直接引用其他的对象,所以对象可以更容易的进行单元测试。

类之间的低耦合可以使类在不影响其他类的基础上进行修改。

? 调停者模式举例

? eg1. WTO组织:它是一个协调组织,它将各贸易区自行进行的相互协调

的强耦合变成了松散合;

?

eg2. 4个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,某人担任调停者,各MM按照各自的筹码数算钱,赚了钱的从调停者这里拿,赔了钱的也付给调停者;

eg3. 租赁中介:很多人有出租房子的需求,也有不少人需要租房,租赁中介在其中担任了调停者的角色, 疏通了两者之间的复杂关系,也方便了两者。

?

1.28 开闭原则

要求一个系统的设计能够允许系统在无需修改的情况下扩展其功能

1.29 依赖倒转原则

减少对象之间的耦合有利于系统的复用

本文来源:https://www.bwwdw.com/article/76f5.html

Top