在上一篇Android源码中的静态工厂方法中我门一起研究了工厂模式三兄弟中最简单的静态工厂方法。今天我们来一起看看三兄弟中的老二————工厂方法模式,以及它在Android源码中的体现。
今天我们先来模拟一个场景,把这三兄弟拎出来给大家瞅瞅,以免以后大家认错。
这就是工厂三兄弟。
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
工厂方法模式所涉及到的角色:
我们用我们上边手机的例子来实现。
抽象产品角色
abstract class APhone {
//所有产品类的公共业务方法
public void methodSame() {
//公共方法的实现
}
//声明抽象业务方法
public abstract void methodDiff();
}
具体产品角色类,这里我们只说一类,比如我们的aPhoneNote系列手机
class APhoneNote1 extends APhone {
//实现业务方法
public void methodDiff() {
//业务方法的实现
}
}
抽象工厂角色
abstract class Factory {
//静态工厂方法
public abstract APhone createProduct(String arg);
}
具体工厂角色,这里我们只说生产aPhoneNote系列手机的工厂
class ConcreteFactory {
//静态工厂方法
public APhone createProduct(String arg) {
APhone aPhoneNote = null;
if (arg.equalsIgnoreCase("1")) {
aPhoneNote = new APhoneNote1();
//初始化设置product
}
else if (arg.equalsIgnoreCase("2)) {
aPhoneNote = new APhoneNote2();
//初始化设置product
}
return aPhoneNote;
}
}
需要创建复杂对象
需要灵活、可扩展的框架,且具体类型不多
我们在开发中会用到很多数据结构,比如ArrayList,HashMap等。我们先来看下Java中Collection部分的类集框架的简要UML图。
我们知道Iterator是迭代器,用来遍历一个集合中的元素。而不同的数据结构遍历的方式是不一样的,所以迭代器的实现也是不同的。使用工厂方法模式将迭代器的具体类型延迟到具体容器类中,比较灵活,容易扩展。
List和Set继承自Collection接口,Collection接口继承于Iterable接口。
public interface Iterable {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator iterator();
//省略部分代码
}
所以List和Set接口也会继承该方法。然后我们常用的两个间接实现类ArrayList和HashSet中的iterator方法就给我们构造并返回了一个迭代器对象。
我们找到ArrayList类,查看iterator方法的实现。
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
ArrayListIterator类型定义如下:
private class ArrayListIterator implements Iterator {
/** 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 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 {
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。这就是工厂方法模式。
看是看完了,但是,总要给我们一个这么做的理由吧?
个人认为,这样设计使得我们的代码结构变得更清晰,同是比较容易扩展,因为我们已经定义好了一套标准,只要按照规矩来就好了。
同时耦合度降低了,高层模块只需要知道产品的抽象类,无所谓具体怎么实现这个产品。