2. 简单工厂模式的简略类图:
3. 简单工厂模式的一般性结构:
4. 简单工厂模式就是由一个工厂类可以根据传入的参量决定创建出哪一种产品类的实例:
简单工厂模式涉及到工厂角色、抽象产品角色以及具体产品角色等三个角色:
a) 工厂类(Creator)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java 类实现。
b) 抽象产品(Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个Java 接口或者Java 抽象类实现。
c) 具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体Java 类实现。
5. 简单工厂模式的示意性源代码如下:
//工厂 public class Creator { /** * 静态工厂方法 */ public static Product factory() { return new ConcreteProduct(); } } //抽象产品 public interface Product { } //具体产品 public class ConcreteProduct implements Product { public ConcreteProduct(){} }
6. 如果产品形成复杂的等级结构,简单工厂模式采取的是以不变应万变的策略,一律使用同一个工厂类:
这样做的好处是设计简单,产品类的等级结构不会反映到工厂类中来,从而产品类的等级结构的变化也就不会影响到工厂类。但是这样做的缺点是,增加新的产品必将导致工厂类的修改。
7. 每个工厂类可以有多于一个的工厂方法,分别负责创建不同的产品对象。
8. 在有些情况下, 工厂角色可以由抽象产品角色扮演。一个抽象产品类同时是子类的工厂。
9. 工厂方法可以循环使用已经创建出来的对象,而不是每一次都创建新的产品对象。工厂方法可以通过登记它所创建的产品对象来达到循环使用产品对象的目的。
10.单例模式使用了简单工厂模式。单例类具有一个静态工厂方法提供自身的实例。但是单例模式并不是简单工厂模式的退化情形,单例模式要求单例类的构造子是私有的,从而客户端不能直接将之实例化,而必须通过这个静态工厂方法将之实例化,而且单例类自身是自己的工厂角色。单例类使用一个静态的属性存储自己的惟一实例,工厂方法永远仅提供这一个实例。
11.多例模式是对单例模式的推广。多例模式与单例模式的共同之处在于它们都禁止外界直接将之实例化,同时通过静态工厂方法向外界提供循环使用的自身的实例。它们的不同在于单例模式仅有一个实例,而多例模式则可以有多个实例。多例模式往往具有一个聚集属性,通过向这个聚集属性登记已经创建过的实例达到循环使用实例的目的。
12.单例和多例模式使用了一个属性或者聚集属性来登记所创建的产品对象,以便可以通过查询这个属性或者聚集属性找到和共享已经创建了的产品对象。这就是备忘录模式的应用:
13.MVC 模式并不是严格意义上的设计模式,而是在更高层次上的架构模式:
简单工厂模式所创建的对象往往属于一个产品等级结构,这个等级结构可以是MVC模式中的视图(View);而工厂角色本身可以是控制器(Controller)。一个MVC 模式可以有一个控制器和多个视图:
控制器端可以创建合适的视图端,就如同工厂角色创建合适的对象角色一样;而模型端则可以充当这个创建过程的客户端。如果系统需要有多个控制器参与这个过程的话,简单工厂模式就不适用了,应当考虑使用工厂方法模式。
14.模式的优点:模式的核心是工厂类。这个类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
15.模式的缺点:
a) 当产品类有复杂的多层次等级结构时,工厂类只有它自己。这个工厂类集中了所有的产品创建逻辑,它不工作了整个系统就瘫痪了,会成为整个系统的瓶颈。
b) 当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展时较为困难。这一缺点在工厂方法模式中得到克服。
c) 由于简单工厂模式使用静态方法作为工厂方法,而静态方法无法由子类继承,因此,工厂角色无法形成基于继承的等级结构。这一缺点会在工厂方法模式中得到克服。
16.Java中的应用:DateFormat 类是一个抽象类,但是却提供了很多的静态工厂方法,比如getDateInstance()为某种本地日期提供格式化,它由三个重载的方法组成:
public final static DateFormat getDateInstance(); public final static DateFormat getDateInstance(int style); public final static DateFormat getDateInstance(int style, Locale locale);
getDateInstance()方法并没有调用DateFormat 的构造子来提供自己的实例,作为一个工厂方法,getDateInstance()方法返回的是SimpleDateFormat 的实例:
17.在SAX2 库中,XMLReaderFactory 类使用了简单工厂模式,用来创建产品类XMLReader 的实例。XMLReaderFactory 提供了两种不同的静态方法,适用于不同的驱动软件参数: