1、定义:
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses.
定义一个用于创建对象的接口,让子类决定实例化哪个类。
2、意义:
工厂方法使得类的实例化延伸到子类。
3、四大角色:
3.1、抽象工厂:工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。
3.2、具体工厂:实现了抽象工厂接口的具体JAVA类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建导出类。
3.3、抽象角色:工厂方法模式所创建的对象的超类。
3.4、具体角色:实现抽象角色的某个具体角色的实例。
4、优点:
4.1、工厂方法模式是完全符合开闭原则的;
4.2、摈弃了简单工厂模式的缺点;
4.3、工厂模式是一种典型的解耦模式,可以降低对象之间的耦合度;
4.4、工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。
4.5、可以使代码结构清晰,有效地封装变化。
4.6、对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
5、缺点:
简单的对象应用时,不适合工厂方法模式。
6、写了一个简单的demo:
首先是普通的 抽象 对象
<span style="font-size:14px;">package com.example.demo.FactoryMethod; /** * 抽象</span><span style="font-size:12px;"><span style="font-family: Arial;">角色</span> </span><span style="font-size:14px;"> * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public interface Lottery { public String getLotteryName(); } </span>
实现:
package com.example.demo.FactoryMethod; /** * 具体角色 * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public class SSQLottery implements Lottery{ @Override public String getLotteryName() { return "双色球"; } } package com.example.demo.FactoryMethod; /** * 具体角色 * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public class DLTLottery implements Lottery{ @Override public String getLotteryName() { return "大乐透"; } }
然后是核心的 抽象工厂:
package com.example.demo.FactoryMethod; /** * 抽象工厂 * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public interface LotteryFactory { public Lottery getLottery(); }
具体工厂:
package com.example.demo.FactoryMethod; /** * 具体工厂 * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public class SSQFactory implements LotteryFactory{ @Override public Lottery getLottery() { return new SSQLottery(); } } package com.example.demo.FactoryMethod; /** * 具体角色 * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public class DLTLottery implements Lottery{ @Override public String getLotteryName() { return "大乐透"; } }
使用:
package com.example.demo.FactoryMethod; import android.util.Log; /** * 工厂方法的使用 * * @author qubian * @data 2015年6月4日 * @email [email protected] * */ public class UseFactory { private static final String TAG="UseFactory"; public void use() { //若是需要修改,只需要修改 new SSQFactory(); 即可; // LotteryFactory factory= new SSQFactory(); //此处的操作完成是,接口的操作; // 也就是说:使用工厂模式,调用者只关心产品的接口就可以了, //至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。 Lottery lottery = factory.getLottery(); Log.i(TAG,lottery.getLotteryName()); } }
在Android中的使用广泛,其中:
1、 关于ArrayList,HashSet,与 Iterator
之间都能算是一种工厂方法;
Set<String> set = new HashSet<String>(); Iterator<String> iterator = set.iterator(); while(iterator.hasNext()) { // 具体操作 } List<String> list =new ArrayList<String>(); Iterator<String> it = list.iterator(); while(it.hasNext()) { // 具体操作 }
其中List和Set都是工厂接口
/** * A {@code Set} is a data structure which does not allow duplicate elements. * * @since 1.2 */ public interface Set<E> extends Collection<E> { /** * Returns an iterator on the elements of this {@code List}. The elements are * iterated in the same order as they occur in the {@code List}. * * @return an iterator on the elements of this {@code List}. * @see Iterator */ public Iterator<E> iterator(); } /** * A {@code List} is a collection which maintains an ordering for its elements. Every * element in the {@code List} has an index. Each element can thus be accessed by its * index, with the first index being zero. Normally, {@code List}s allow duplicate * elements, as compared to Sets, where elements have to be unique. */ public interface List<E> extends Collection<E> { /** * Returns an iterator on the elements of this {@code List}. The elements are * iterated in the same order as they occur in the {@code List}. * * @return an iterator on the elements of this {@code List}. * @see Iterator */ public Iterator<E> iterator(); }
自然,ArrayList与HashMap 都有关于其中的实现了。
public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess { @Override public Iterator<E> iterator() { return new 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; } } }