【1】基本概念
FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化。
【2】简单分析
我们先来看一下该设计模式的UML图:
上图是Factory Method 模式的结构图,让我们可以进行更方便的描述:
- Product: 需要创建的产品的抽象类.
- ConcreteProduct: Product的子类,一系列具体的产品.
- Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method.
- ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,返回ConcreteProduct类型的实例.
同时可以清楚的看出这样的平行对应关系: Product <====> Creator ; ConreteProduct <====> ConreteCreator
抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过Factory Method模式来完成,客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和ConcreteCreator可以毫不关心,这样做我们可以获得额外的好处:
- 首先客户端可以统一从抽象创建器获取产生的实例,Creator的作用将client和产品创建过程分离开来,客户不用操心返回的是那一个具体的产品,也不用关心这些产品是如何创建的.同时,ConcreteProduct也被隐藏在Product后面,ConreteProduct继承了Product的所有属性,并实现了Product中定义的抽象方法,按照Java中的对象造型(cast)原则,通过ConcreteCreator产生的ConcreteProduct可以自动的上溯造型成Product.这样一来,实质内容不同的ConcreteProduct就可以在形式上统一为Product,通过Creator提供给client来访问.
- 其次,当我们添加一个新的ConcreteCreator时,由于Creator所提供的接口不变,客户端程序不会有丝毫的改动,不会带来动一发而牵全身的灾难, 这就是良好封装性的体现.但如果直接用ConcreteProduct和ConcreteCreator两个类是无论如何也做不到这点的. 优良的面向对象设计鼓励使用封装(encapsulation)和委托(delegation),而Factory Method模式就是使用了封装和委托的典型例子,这里封装是通过抽象创建器Creator来体现的,而委托则是通过抽象创建器把创建对象的责任完全交给具体创建器ConcreteCreator来体现的.
该模式采用一个Shape(形状)的经典例子作为一个实例来展示如何实现Factory Method模式,先看下代码的结构图:
3.1 首先定义一个抽象类Shape,定义两个抽象的方法.
- package com.andyidea.patterns.product;
- /**
- * Product: 需要创建的产品的抽象类.
- * @author Andy.Chen
- *
- */
- public abstract class Shape {
- public String name;
- public Shape(String aName){
- this.name = aName;
- }
- //绘画
- public abstract void draw();
- //擦除
- public abstract void erase();
- }
Circle中的源码如下:
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.product.Shape;
- /**
- * 圆形子类(ConcreteProduct: Product的子类,一系列具体的产品.)
- * @author Andy.Chen
- *
- */
- public class Circle extends Shape{
- public Circle(String name) {
- super(name);
- }
- @Override
- public void draw() {
- System.out.println("It will draw a Circle");
- }
- @Override
- public void erase() {
- System.out.println("It will erase a Circle");
- }
- }
- package com.andyidea.patterns.concreteproduct;
- import com.andyidea.patterns.product.Shape;
- /**
- * 方形子类(ConcreteProduct: Product的子类,一系列具体的产品.)
- * @author Andy.Chen
- *
- */
- public class Square extends Shape{
- public Square(String name) {
- super(name);
- }
- @Override
- public void draw() {
- System.out.println("It will draw a Square");
- }
- @Override
- public void erase() {
- System.out.println("It will erase a Square");
- }
- }
- package com.andyidea.patterns.creator;
- import com.andyidea.patterns.product.Shape;
- /**
- * Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method.
- * @author Andy.Chen
- *
- */
- public abstract class ShapeFactory {
- protected abstract Shape factoryMethod(String aName);
- public void anOperation(String aName){
- Shape s = factoryMethod(aName);
- System.out.println("The current shape is: " + s.name);
- s.draw();
- s.erase();
- }
- }
CircleFactory中的源码:
- package com.andyidea.patterns.concretecreator;
- import com.andyidea.patterns.concreteproduct.Circle;
- import com.andyidea.patterns.creator.ShapeFactory;
- import com.andyidea.patterns.product.Shape;
- /**
- * ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,
- * 返回ConcreteProduct类型的实例.
- * @author Andy.Chen
- *
- */
- public class CircleFactory extends ShapeFactory {
- @Override
- protected Shape factoryMethod(String aName) {
- return new Circle(aName + " (created by CircleFactory)");
- }
- }
- package com.andyidea.patterns.concretecreator;
- import com.andyidea.patterns.concreteproduct.Square;
- import com.andyidea.patterns.creator.ShapeFactory;
- import com.andyidea.patterns.product.Shape;
- /**
- * ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,
- * 返回ConcreteProduct类型的实例.
- * @author Andy.Chen
- *
- */
- public class SquareFactory extends ShapeFactory {
- @Override
- protected Shape factoryMethod(String aName) {
- return new Square(aName + " (created by SquareFactory)");
- }
- }
- package com.andyidea.patterns.client;
- import com.andyidea.patterns.concretecreator.CircleFactory;
- import com.andyidea.patterns.concretecreator.SquareFactory;
- import com.andyidea.patterns.creator.ShapeFactory;
- /**
- * 测试设计模式类
- * @author Andy.Chen
- *
- */
- public class MainClient {
- public static void main(String[] args) {
- ShapeFactory sf1 = new CircleFactory();
- ShapeFactory sf2 = new SquareFactory();
- System.out.println("Welcome to Andy.Chen Blog!" +"\n"
- +"Factory Method Patterns." +"\n"
- +"-------------------------------");
- sf1.anOperation("Shape-Circle");
- sf2.anOperation("Shape-Square");
- }
- }
- Welcome to Andy.Chen Blog!
- Factory Method Patterns.
- -------------------------------
- The current shape is: Shape-Circle (created by CircleFactory)
- It will draw a Circle
- It will erase a Circle
- The current shape is: Shape-Square (created by SquareFactory)
- It will draw a Square
- It will erase a Square