设计模式学习笔记
创建模式Creational Pattern是对类的实例化过程的抽象化。一些系统在创建对象时,需要动态的决定怎样创建对象,创建哪些对象,以及如何组合和表示这些对象,创建模式描述了怎样构造和封装这些动态的决定。创建模式分为类的创建模式和对象的创建模式俩种:
类的创建模式 使用继承关系,把类的创建延迟到了子类,从而封装了客户端将得到哪些具体类的信息,并且隐藏了这些类的实例是如何被创建和放在一起的。
对象的创建模式 则把对象的创建过程动态低委派给另外一个对象,从而动态地决定客户端将得到哪些具体类的实例,以及这些类的实例是如何被创建和组装到一起。
创建模式包括以下几种:简单工厂模式,工厂方法模式,抽象工厂模式,单例模式,多例模式,建造模式,原始模型模式等
工厂模式专门负责将大量有共同接口的类实例化,工厂模式可以动态决定将那一个类实例化,不必事先知道每次要实例化哪一个类。工厂模式有如下几种形态:简单工厂模式Simple Factory,工厂方法模式Factory Method又称多态性工厂模式Polymorphic Factory或虚拟构造子模式Virtual Constructor.抽象工厂模式Abstract Factory又称工具箱模式Tool kit模式。
简单工厂模式 是类的创建模式,又叫静态工厂方法Static Factory method模式,是由一个工厂对象决定创建出哪一种产品类的实例。是工厂方法模式的一个特殊实现。
从上图可以看出,建单工厂模式涉及到工厂角色模式,抽象产品角色以及具体产品角色等三个角色:
工厂类角色Creator:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java类实现。
抽象产品角色Product:担任这个角色的类是由工厂方法模式创建的对象的父类,或它们共同拥有的接口.抽象产品角色可以由一个Java接口或Java抽象类实现。
具体产品角色Concrete Product:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体的Java类实现。
如果模式所产生的具体产品类彼此之间没有共同的商业逻辑,那么抽象产品角色可以由一个Java接口扮演;相反,如果这些具体产品类彼此之间确实有共同的商业逻辑,那么这些公用的逻辑就应当移动到抽象角色里面。这就意味着抽象角色应当由一个抽象类扮演。
每个工厂类可以由多于一个的工厂方法,分别负责创建不同的产品对象。如DateFormat类。
如果系统只有一个具体产品角色,那么就可以省略掉抽象角色。如果抽象产品角色被省略,那么工厂角色,具体产品角色就可以省略,从而3个角色都合并为一个类,这个类自行创建自己的实例。这种退化的工厂模式与单利模式有相似之处,但是并不等于单例模式。
产品对象的循环使用和登记式的工厂方法。在很多情况下,产品对象可以循环使用。换言之,工厂方法可以循环使用已经创建出来的对象,而不是每次都创建一个新的对象。工厂方法可以通过登记它所创建的产品对象来达到循环使用产品对象的目的。
如果工厂方法总是循环使用同一个产品对象,那么工厂方法可以使用同一个属性来存储这个产品对象。单例模式就是如此。一个永远只提供一个产品对象的工厂对象可以使用一个静态的属性变量存储对这个产品对象的引用。
如果工厂方法总是循环使用固定数目的一些产品对象,而且这些产品对象的数目量不大的话,可以用一些私有属性存储这些产品对象的引用。
如果工厂方式使用的产品对象的数目不确定,或者产品对象的数目量大的话,应该使用集合存储这些产品对象的引用。
简单工厂方法模式和其它模式的关系:
单例模式使用了简单工厂模式。换言之,单例类具有一个静态工厂方法提供自身实例。一个抽象产品类同时是子类的工厂。但是单例模式不是简单工厂方法模式的退化情形,单例模式要求单例类的构造方法是私有的,从客户端不能直接实例化,必须通过这个静态工厂方法将其实例化。而且单例类自己是自己的工厂角色。单例类自己负责创建自身的实例。
单例类使用一个静态的属性存储自己唯一的实例,工厂方法永远提供这一个实例。
多例模式是单例模式的推广。多例模式与单例模式的共同之处是它们都禁止了外界将其直接实例化,同事通过静态工厂方法向外界提供循环使用的自身的实例。它们的不同仅在于单例模式仅有一个实例,而多例模式可以有多个实例。多例模式往往内部拥有一个集合属性,通过向这个集合登记已经创建过的实例达到循环使用实例的目的。一般而言,一个典型的多例模类具有某种内部状态,这个内部状态可以用来区分各个实例,而对应于每一个内部状态,都只有一个实例存在。根据外部传入的参量,工厂方法可以查询自己的集合里登记的实例,如果有这个状态的实例,则直接返回。反之,先创建登记,后返回给客户端使用。
备忘录模式:单例模式或多例模式使用一个属性或集合属性来登记所创建的产品对象,以便可以通过查询这个属性或者集合来找到并共享已经创建的产品对象。这就是备忘录模式的应用。体现向外提供不同的接口。
MVC并不是严格意义上的设计模式,而是更高层次的架构模式。MVC模式可以分解为几个设计模式的组合,包括合成模式,策略模式,观察者模式,也可能会有装饰模式,调停者模式,迭代子模式以及工厂方法模式等。MVC中controller可以比作工厂,view可以比作具体的产品对象。
简单工厂模式的核心是工厂类。这个类还有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。而客户端则可以直接免除创建产品对象的责任,而仅仅负责消费产品,简单工厂模式通过这种方式实现了对责任的分割。
简单工厂模式的缺点:当产品类有复杂的等级结构时,工厂类只有它自己,以不变应万变,这就是缺点。工厂类集中了所有产品的创建逻辑,形成一个无所不知的全能类。负责了太多职责。一旦工厂类出现问题系统就出现问题了。另外一个缺点是当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品,这种对时机的判断和对具体产品的判断逻辑混合在一起,不便于以后的扩展。另一点是简单工厂方法的模式的工厂方法是静态工厂方法,静态方法无法有子类继承,工厂角色无法形成继承等级结构来扩展。这些在工厂方法模式中得到克服。
简单工厂方法模式在有限的程度上实现了开闭原则OCP,即体现在引进新的产品上。这一点对产品的消费角色是成立的,但是对工厂角色是不成立的,因为工厂角色在引进新的产品时需要修改。
DateFormat是一个抽象类,他的getDateInstance()通过多态返回具体子类的实例,而且这是个静态方法,如果是非静态方法,获取子类的格式化方法需要实例化子类的对象才能实现。实际上一是多态,二是静态工厂方法。public final static DateFormat getDateInstance(); DateFormat是抽象类,从而可以实现多态的子类的返回。 这里的工厂角色和抽象产品角色合并为一个类。换言之,是抽象产品角色负责具体产品的创建,这是简单工厂方法模式的一个特例。
SAX2库中的XMLReaderFactory是使用了简单工厂模式。使用了俩个不同的静态方法来创建产品类XMLReader的实例。
工厂方法模式是类的创建模式,又叫虚拟构造模式virtual Contructor模式或多态性工厂模式polymorphic Factory。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
工厂方法模式是对简单工厂模式的进一步抽象。由于简单工厂模式在引入新产品类的时候需要修改工厂方法,这在一定程度上不满足开闭原则OCP,但是从客户端角度看,简单工厂模式引入新产品时无需修改客户端,是符合开闭原则的。工厂方法模式保持了简单工厂模式的优点,克服了简单工厂模式的缺点。
工厂方法模式中,核心的工厂类不在负责所有产品的创建,而是将具体的创建工作交给子类去去做。在简单工厂模式中的工厂类,在工厂方法模式中变成一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。进一步抽象出工厂角色的结果使工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引入新的产品。
在一个系统设计中,常常是现有产品角色,再有工厂角色。在可以应用工厂方法模式的前提下,一般都会有一个产品登记结构,由一个或多个抽象产品和多个具体产品组成。等级结构如树图。 这种多层等级结构中,出现多于一个的抽象产品类,以及多余俩个的层次。当将工厂方法模式应用到这个系统中的时候,常常采用的一个做法是按照产品的等级结构设计一个同等级结构的工厂等级结构。
然后由相应的工厂角色创建相应的产品角色。工厂方法模式的应用如下图:
一般的类图如下:
工厂方法模式涉及的系统角色有如下:
抽象工厂Creator角色:担任这个角色的是工厂方法模式的核心。任何在模式中创建对象的工厂都必须实现这个接口。也可以由抽象类替代。
具体工厂角色Concrete Creator:担任这个角色的是实现了抽象工厂接口角色的具体Java类。具体工厂角色含有与应用程序密切相关的逻辑,并且受到应用程序的调用以创建具体的产品对象。
抽象产品Product角色:工厂方法模式所创建的对象的父类型。也就是产品对象共同的父类或者是共同拥有的接口。
具体产品Concrete Product角色:这个角色实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的子类的实例。
客户端角色:这个角色创建工厂对象,并调用工厂对象的工厂方法创建相应的产品对象。
在客户端调用工厂方法模式时,返回的是一个具体的产品对象,但是类型是抽象的产品对象。
Java.util.Collection接口的Iterator()返回的是一个Iterator类型的对象,也是工厂方法模式的应用。
Java.net.URL的openConnection()方法返回一个URLConnection类型的对象,URLConnection是抽象类,也是工厂方法模式的应用。
享元模式使用了带有循环逻辑的工厂方法。
备忘录模式通过查找内部集合内部已经从创建了的对象,也是工厂方法模式。
EJB通过Home接口创建home对象也是工厂模式。
JMS也使用了工厂模式。如下图:
抽象工厂模式:
左边的等级结构代表工厂等级结构,右边的等级结构代表俩个产品等级结构。抽象工厂模式可以向客户端提供一个接口,使得客户端并不比指定具体的产品类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂模式的用意。
工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要有多个产品等级结构。抽象工厂模式是对象的创建模式。假设一个系统需要一些产品对象,而这些对象又属于一个以上的产品等级结构,那么为了将消费这些产品对象的责任和创建这些产品对象的责任分割开来,就需要引进抽象工厂模式。这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公用的工厂接口请求所需要的产品。
抽象工厂模式设计出的类图如下:
抽象工厂角色AbstractFactory:担任这个角色的是工厂方法模式的核心角色,它是与应用系统的商业逻辑无关的。通常使用Java接口或抽象类是想,而所有的具体工厂类必须实现这个Java接口或抽象类。
具体工厂角色Concrete Factory:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑无关的。通常使用具体Java类实现这个角色。
抽象产品角色Abstract Product:担任这个角色的类是工厂方法模式创建的对象的父类,或它们共同拥有的接口。通常使用Java接口或抽象类实现。
具体产品Concrete product角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西。其内部一定充满了应用系统的商业逻辑。通常使用具体类实现这个角色。
在本例中有俩个产品等级结构,而每个产品等级结构又有俩个产品。也就是俩个产品族。因此工厂等级结构中就会出现俩个具体工厂(对应于俩个具体产品族);而每个工厂类中又有俩个工厂方法(对应于俩个产品等级结构)
抽象工厂使用的情形:
a.一个系统不应当依赖于产品类实例如何被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。
b.这个系统的产品有多于一个的产品族,而系统只消耗某一族的产品;(这是抽象共产的原始用意)
c.系统提供一个产品类的库,所有的产品以同样的接口出现。从而是客户端不依赖于实现。
如下例:
农场里引进热带Tropical的水果和蔬菜的大棚种植业务,和以前经营的产品北方的水果fruit和蔬菜Veggie的角色相图。
工厂Gardener的等级结构应该与产品的等级结构完全平行。系统设计的图如下:
体会一下有几个产品族就应该有几个具体的工厂类,有几个产品类型的等级结构具体工厂方法里就应该有几个方法。这里有俩个产品族Tropical和northern就有俩个具体工厂的子类。有俩个类型的等级结构fruit和Veggie具体工厂方法里就有俩个方法。
另一个例子是描述计算机配件的生产。这个系统所需要的产品族有俩个,一个是IBM的PC系列,另一个是MAC系列MacIntosh,产品等级结构也有俩个,一个是Ram,一个是cpu。考虑这个如何设计?
开闭原则OCP要求不修改原有代码的情况下,通过扩展增强系统的功能。对于一个涉及到多个产品等级结构和多产品族的系统。其功能增强不外乎俩方面:a.增加新的产品的族 b.增加产品的等级结构。
在产品等级结构数目不变的情况下,增加新的产品族,就意味着在每一个产品等级结构中增加一个或多个新的具体的或抽象的产品角色。由于工厂等级结构与产品等级结构时平行的登记关系。当产品等级结构有所调整时,工厂等级结构也有相应的调整。产品等级结构出现了新的元素,工厂等级结构中加入相应的新元素就可以了,不必修改已有的工厂角色或产品角色。抽象工厂模式支持开闭原则的。
在产品族数目不变的情况下,增加新的产品等级结构。换言之,所有的产品等级结构中的产品数目不会改变。但是现在多出一个与现有产品等级结构平行的新的产品等级结构。要做到这一点,就需要修改所有的工厂角色,给每个工厂类都增加一个新的工厂方法。这是违反开闭原则OCP的。换言之,对于工厂等级结构的增加,抽象工厂模式,不支持开闭原则。综合而言,抽象工厂模式以一种倾斜的方式支持增加新的产品。它为新的产品族的增加提供方便,而不能为新的产品等级结构的增加提供方便。
具体工厂类可以设计成单例模式的类。如农场的TropicGardern和northernGardern
工厂角色可以和抽象的产品角色(具体产品)合并,如DateFormat。在抽象工厂模式中,抽象工厂类可以配备静态的工厂方法,已返回具体工厂的实例。依赖产量的值来返回具体工厂的实例,静态方法的返回类型是抽象工厂类型,可以保证多态的灵活性。
工厂角色可以和具体工厂角色合并。这意味着要为每一个具体工厂类配备一个静态方法,而其返回类型应该是该具体工厂类自己。
抽象工厂模式,可以通过原始模型模式prototype实现。抽象工厂模式通过工厂方法模式实现时,每一个工厂角色都配有一个工厂方法,这个方法负责调用构造方法,将产品角色实例化。 考虑通过原始模型模式如何实现?
抽象工厂模式可以为桥梁模式提供某一个等级结构的创建功能。如Java Awt的peer架构使用抽象模式。
相关推荐
java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式java设计模式之工厂模式...
根据提供的标题“深入浅出设计模式之工厂模式”与描述“将《Head First 设计模式》(中文版)按章节进行了分割,每章一个文件,方便大家下载”,我们可以推测出这部分内容主要关注的是设计模式中的工厂模式。...
在这个"菜鸟教程设计模式之工厂模式代码整理"中,我们将深入探讨工厂模式的基本概念、结构以及如何在实际编程中应用。 工厂模式的核心思想是通过一个专门的工厂类来创建对象,而不是让客户端代码直接实例化具体的...
### JAVA设计模式之工厂模式 #### 一、工厂模式概述 工厂模式是一种常见的设计模式,主要应用于当系统中存在大量的类实例化需求时。通过工厂模式,我们可以避免直接使用`new`关键字创建对象,而是通过工厂类来创建...
在这个“菜鸟教程设计模式之工厂模式代码整理(反射机制改进版)”中,我们主要探讨的是如何利用Java的反射机制来进一步增强工厂模式的功能。 首先,理解工厂模式的基本概念。工厂模式属于创建型设计模式,它提供了...
工厂方法(Factory Method)是工厂模式的一种具体实现,它是《Head First 设计模式》这本书中讲解的重点之一。在这个模式中,一个工厂类声明了一个创建对象的抽象方法,但并不实现这个方法。而是由子类决定要实例化...
JAVA设计模式之工厂模式是软件开发中一种常用的设计模式,它专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。 一、工厂模式的介绍 工厂模式有三种...
### Java设计模式之工厂模式详解 #### 一、引言 设计模式是在软件设计过程中针对常见问题而提出的标准化解决方案。其中,“工厂模式”是面向对象编程中最常用的模式之一,主要目的是封装实例化过程,使代码更加...
【Java设计模式之工厂模式Factory】是面向对象编程领域中常用的设计模式,它提供了一种创建对象的最佳方式。工厂模式的主要思想是将对象的创建过程封装起来,使得客户端(使用对象的代码)无需关心对象的具体创建...
在软件开发中,设计模式是经验丰富的开发者们总结出的解决常见问题的模板或最佳实践。工厂模式作为其中的一种,是对象创建型模式,它的主要目的是为了隔离对象创建过程与客户端之间的关系,使得创建过程更加灵活,...
Java设计模式之工厂模式(Factory).doc