概念

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。

工厂方法模式是一种实现了「工厂」概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。

在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

模式结构

工厂方法模式包含如下角色:

类图

img1.png

代码实现

还是以水果的例子来看看代码:

//抽象产品:Fruit
public abstract class Fruit {
	
	public abstract void eat();
	
}

//--------------------------

//具体产品:Apple、Banana
public class Apple extends Fruit{

	@Override
	public void eat() {
		System.out.println("吃了一个苹果");
	}

}
public class Banana extends Fruit{

	@Override
	public void eat() {
		System.out.println("吃了一个香蕉");
	}

}

//-------------------------------

//抽象的工厂类(接口实现)IFactory
public interface IFactory {
	
	Fruit createFruit();

}

//--------------------------

//每个具体产品都对应一个具体的工厂类AppleFactory、BananaFactory

public class AppleFactory implements IFactory{

	public Fruit createFruit() {
		
		return new Apple();
	}

}

public class BananaFactory implements IFactory{

	public Fruit createFruit() {
		return new Banana();
	}

}

//---------------------------

//main方法中调用
public class Test {
	
	public static void main(String[] args) {
		
		Fruit f1 = new AppleFactory().createFruit();
		f1.eat();
		Fruit f2 = new BananaFactory().createFruit();
		f2.eat();
	}

}

执行结果如下: 吃了一个苹果 吃了一个香蕉

和简单工厂模式进行比较,最大的区别是:工厂方法模式在设计上完全完全符合「开闭原则」。

当我们想要增加一个产品时,比如水果示例中增加一个 Orange。在简单工厂模式的实现中,需要:

  1. 增加 Orange 类,继承自 Fruit 类(肯定是必须的)
  2. 修改 FruitFactory 类,在 switch 中增加一个 case,在匹配到 orange 时返回一个 Orange 实例。

很显然,这样的操作是不符合开闭原则(对扩展开放,对修改封闭)的,我们希望在增加新的功能时,不去修改原有的代码。

而在工厂方法模式中,需要:

  1. 增加 Orange 类,继承自 Fruit 类(和简单工厂一样)
  2. 增加一个 OrangeFactory 的工厂类,实现 IFactory 接口,返回一个 Orange 实例。

可以看到,工厂方法模式的实现中,不需要修改任何原有的代码,只是增加了一对产品类和相应的工厂类,是符合开闭原则的。

适用场景

在以下情况下可以使用工厂方法模式:

优缺点

优点:

缺点:

Android 中工厂方法的应用

Java中的集合框架

在 Android 开发中会用到很多数据结构,比如 ArrayList,HashMap 等。先来看下 Java 中 Collection 部分的类集框架的简要 UML 图。

img2.png

我们知道 Iterator 是迭代器,用来遍历一个集合中的元素。而不同的数据结构遍历的方式是不一样的,所以迭代器的实现也是不同的。使用工厂方法模式将迭代器的具体类型延迟到具体容器类中,比较灵活,容易扩展。

List和Set继承自Collection接口,Collection接口继承于Iterable接口。

public interface Iterable<T> {
 
    Iterator<T> iterator();

    //省略部分代码
}

所以List和Set接口也会继承该方法。然后我们常用的两个间接实现类ArrayList和HashSet中的iterator方法就给我们构造并返回了一个迭代器对象。

ArrayList 类中 iterator() 方法的实现:

Override 
public Iterator<E> iterator() {
    return new ArrayListIterator();
}

ArrayListIterator类型定义如下:

private class ArrayListIterator implements Iterator<E> {
    /** Number of elements remaining in this iteration */
    private int remaining = size;

    /** Index of element that remove() would remove, or -1 if no such elt */
    private int removalIndex = -1;

    /** The expected modCount value */
    private int expectedModCount = modCount;

    public boolean hasNext() {
        return remaining != 0;
    }

    @SuppressWarnings("unchecked") public E next() {
        ArrayList<E> ourList = ArrayList.this;
        int rem = remaining;
        if (ourList.modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (rem == 0) {
            throw new NoSuchElementException();
        }
        remaining = rem - 1;
        return (E) ourList.array[removalIndex = ourList.size - rem];
    }

    public void remove() {
        Object[] a = array;
        int removalIdx = removalIndex;
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (removalIdx < 0) {
            throw new IllegalStateException();
        }
        System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
        a[--size] = null;  // Prevent memory leak
        removalIndex = -1;
        expectedModCount = ++modCount;
    }
}

这个类实现了Iterator接口,接口的定义如下:

public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

基本的结构分析完了,接下来对号入座,看一看具体是如何实现工厂方法模式的。

Iterator————>Product;ArrayListIteratorr————>ConcreteProduct。

Iterable/List————>Factory;ArrayList————>ConcreteFactory。

工厂方法使一个类的实例化延迟到子类,对应着将迭代器 Iterator 的创建从 List 延迟到了ArrayList。这就是工厂方法模式。

参考资料

工厂方法模式(Factory Method Pattern)

设计模式(五)——工厂方法模式

Android中的工厂方法模式