通过一的文章,我们知道简单工厂是不符合开闭原则的,而工厂模式刚好可以解决此缺陷。
定义
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类
工厂方法让类的实例化推迟到子类中进行
适用场景
- 创建对象需要大量的重复代码
- 客户端不依赖与产品实例如何被创建、实现等细节
- 一个类通过其子类来指定创建哪个对象
代码示例
同样是上一节的生产Cpu的业务场景,这次我们用工厂模式来进行创建
- 产品类的定义
public interface Cpu
{
void produce();
}
public class KirinCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("华为麒麟处理器");
}
}
public class MtkCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("联发科处理器");
}
}
public class SnapdragonCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("高通骁龙处理器");
}
}
在这里我们创建一个Cpu产品的接口,并定义了它的三个实现类
- 接下来我们定义工厂类的接口和实现
首先定义生产Cpu的工厂,这里应该定义为抽象类或接口,而具体的实现交给工厂实现类
public abstract class CpuFactory
{
public abstract Cpu getCpu();
}
我们同样定义三个工厂实现类
public class KirinCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new KirinCpu();
}
}
public class MtkCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new MtkCpu();
}
}
public class SnapdragonCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new SnapdragonCpu();
}
}
- 在客户类中我们就可以直接调用某个产品对应的工厂类来生产该产品
public class Client
{
public static void main(String[] args)
{
CpuFactory cpuFactory1 = new MtkCpuFactory();
CpuFactory cpuFactory2 = new SnapdragonCpuFactory();
CpuFactory cpuFactory3 = new KirinCpuFactory();
Cpu cpu1 = cpuFactory1.getCpu();
Cpu cpu2 = cpuFactory2.getCpu();
Cpu cpu3 = cpuFactory3.getCpu();
cpu1.produce();
cpu2.produce();
cpu3.produce();
}
}
其UML类图如下
扩展性
工厂模式解决了简单工厂模式的扩展性问题,当要添加新的产品的时候,我们只需要新建一个该产品对应的工厂类。
缺点
工厂模式虽然符合开闭原则,但是它本身也带来了一些新的问题
- 类的个数过多,容易增加复杂度
- 增加了系统的抽象性和理解难度
应用
Collection类的iterator()方法
Collection应该是我们在java里非常熟悉的接口了,我们常用的许多各种数据结构都是该接口的实现。而iterator()方法的声明如下
Iterator<E> iterator();
其返回的Iteartor对象是一个接口
java中的ArrayList是Collection接口的实现,而其也必定实现了该工厂方法。它的具体实现代码如下
public Iterator<E> iterator() {
return new Itr();
}
该方法返回了一个ArrayList的Iterator的实现,其定义在ArrayList内部,是一个内部类,类的声明如下
private class Itr implements Iterator<E>
同样我们也可以在LinkedList找到其对应的实现类以及实现方法,在此就不展示了
slf4j中的ILoggerFactory
我们在用slf4j获取日志时经常会调用以下方法来获取日志
Logger logger = LoggerFactory.getLogger(getClass());
其内部实现如下
而ILoggerFactory是一个接口,代表生成logger对象的工厂,注意Logger也是一个接口
其定义如下
public interface ILoggerFactory {
public Logger getLogger(String name);
}
它有以下实现类
在这里Logger相当于Cpu,ILoggerFactory相当于CpuFactory,而我们获得的Logger对象是由对应的ILoggerFactory的实现生成的