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 naibbian@163.com
*
*/
public interface Lottery {
public String getLotteryName();
}
</span>
实现:
package com.example.demo.FactoryMethod;
/**
* 具体角色
* @author qubian
* @data 2015年6月4日
* @email naibbian@163.com
*
*/
public class SSQLottery implements Lottery{
@Override
public String getLotteryName() {
return "双色球";
}
}
package com.example.demo.FactoryMethod;
/**
* 具体角色
* @author qubian
* @data 2015年6月4日
* @email naibbian@163.com
*
*/
public class DLTLottery implements Lottery{
@Override
public String getLotteryName() {
return "大乐透";
}
}
然后是核心的 抽象工厂:
package com.example.demo.FactoryMethod;
/**
* 抽象工厂
* @author qubian
* @data 2015年6月4日
* @email naibbian@163.com
*
*/
public interface LotteryFactory {
public Lottery getLottery();
}
具体工厂:
package com.example.demo.FactoryMethod;
/**
* 具体工厂
* @author qubian
* @data 2015年6月4日
* @email naibbian@163.com
*
*/
public class SSQFactory implements LotteryFactory{
@Override
public Lottery getLottery() {
return new SSQLottery();
}
}
package com.example.demo.FactoryMethod;
/**
* 具体角色
* @author qubian
* @data 2015年6月4日
* @email naibbian@163.com
*
*/
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 naibbian@163.com
*
*/
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;
}
}
}