工厂方法模式
学前先了解一下:简单工厂方法的介绍
定义: 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类进行
类型: 创建型
适用场景
- 创建对象需要大量重复代码
- 客户端(应用层)不依赖于产品类如何被创建、实现等细节
- 一个类通过其子类来指定创建哪个对象
优点与缺点
优点:
- 用户只需要关心所需要产品对应的工厂,无需关心创建细节
- 加入新产品符合开闭原则,提高可拓展性。
缺点:
- 类的个数容易多多,增加复杂度
- 增加了系统的抽象性和理解难度
编码实现工厂方法模式(Java)
//抽象产品类
public abstract class Video {
public abstract void produce();
}
//具体产品类
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("produce java video");
}
}
//具体产品类
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("produce python video");
}
}
public interface VideoFactory {
//抽象方法
Video getInstance();
}
//工厂的具体实现交给子类。与简单工厂的最大区别,完成产品与工厂的解耦
public class JavaVideoFactory implements VideoFactory {
@Override
public Video getInstance() {
return new JavaVideo();
}
}
public class PythonVideoFactory implements VideoFactory {
@Override
public Video getInstance() {
return new PythonVideo();
}
}
工厂方法将具体的产品实例化的内容延迟给其子类去实现。
对于这个例子:javaFactory -> javaVideo ,对比简单工厂: videoFactory -> javaVideo | | pythonVideo 具体产品与工厂耦合,需要判断逻辑,且破坏开闭原则。
工厂方法则利用里氏替换,实现低耦合,但会可能引发子类过多等情况,也就违反了违反了高内聚责任分配原则。
UML
jdk中的一处工厂方法的实现
其实我们最熟悉的collection
以及ArrayList
就是结合了工厂方法的一个实现。
//collection类中定义一个工厂方法来返回一个迭代器,迭代器即是抽象产品
Iterator<E> iterator();
//返回一个内部类的实例,对工厂方法的具体实现。ArrayList实现自List接口,List继承自Collection
public Iterator<E> iterator() {
return new Itr();
}
//在ArrayList中定义了一个内部类实现了Iterator,即为具体产品
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
希望通过这个例子,可以更了解工厂方法,以及简单工厂。
源码地址:https://github.com/DiangD/design_pattern_practice