设计模式 | 工厂方法及相关应用
工厂方法(Factory Method)
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
适用场景:
- 创建对象需要大量重复的代码
- 客户端不依赖于产品类示例如何被创建、实现等细节
- 一个类通过其子类来指定创建哪个对象
优缺点
优点:用户只需要关心所需产品对应的工厂,无需关心创建细节;加入新产品符合开闭原则,提高可扩展性。
缺点:类的个数容易过多,增加复杂度。
应用场景
抽象产品类Video
:
public abstract class Video {
public abstract void produce();
}
具体产品类JavaVideo
、PythonVideo
:
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
抽象工厂类VideoFactory
:
public abstract class VideoFactory {
public abstract Video getVideo();
}
具体工厂类JavaVideoFactory
、PythonVideo
:
public class JavaVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
}
public class PythonVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
}
客户端类Test
:
public class Test {
public static void main(String[] args) {
VideoFactory videoFactory = new PythonVideoFactory();
VideoFactory videoFactory2 = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
}
}
这时如果需要增加一个新的产品时,只需要添加一个新的具体产品类和具体工厂类,而无需像简单工厂一样修改工厂类里面的判断逻辑,即满足了开闭原则。
例如,如果要增加新产品FEVideo,我们需要先加入一个具体产品类:
public class FEVideoFactory extends VideoFactory{
@Override
public Video getVideo() {
return new FEVideo();
}
}
再增加这个具体产品所对应的具体工厂类:
public class FEVideoFactory extends VideoFactory{
@Override
public Video getVideo() {
return new FEVideo();
}
}
之后在应用层就可以直接使用了:
public class Test {
public static void main(String[] args) {
VideoFactory videoFactory = new PythonVideoFactory();
VideoFactory videoFactory2 = new JavaVideoFactory();
VideoFactory videoFactory3 = new FEVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
}
}
此时的UML类图:
Java集合接口Collection中的应用
java.util.Collection
接口下的iterator()
方法:
public interface Collection<E> extends Iterable<E> {
//...
Iterator<E> iterator();
//...
查看该接口的其中一个实现类ArrayList
:
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
//...
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
//...
}
public void remove() {
//...
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
//...
}
//...
}
在这里,Collection
相当于一个抽象工厂,而ArrayList
相当于一个具体工厂,这个具体工厂实现了工厂方法iterator()
实例化具体产品Itr
,而这个具体产品实现了抽象产品Iterator
。
logback中的应用
由UML可以看出ILoggerFactory
作为抽象的工厂类,实现有三个具体的工厂类,以其中的NOPLoggerFactory
为例,实现了抽象方法getLogger
来实例化具体产品类:
public class NOPLoggerFactory implements ILoggerFactory {
public NOPLoggerFactory() {
}
public Logger getLogger(String name) {
return NOPLogger.NOP_LOGGER;
}
}