简单工厂模式一文中介绍了简单工厂模式的原理以及优缺点。根据简单工厂模式的特点可以知道简单工厂模式就是引入一个工厂来降低耦合,系统使用工厂类生产所有产品实例,且该工厂类决定生产哪个类的实例,即该工厂类负责所有的逻辑判断、实例创建等动作。但是,这样工厂类就过于复杂,如果不想在工厂类中实现复杂的逻辑判断,可以给工厂提供接口,然后为每个产品都设置一个工厂,所有工厂都实现工厂接口。
还是举电脑连接打印设备的例子。假设一个电脑computer类,以及两个打印设备Printer类和BetterPrinter类,如果采用简单工厂模式,则需要在工厂类中进行逻辑判断以及创建哪个设备。而工厂方法模式则是为所有工厂提供了一个接口,而每个工厂类只需要负责创建对象。如下所示:
computer类:
public class Computer
{
private Output out;
public Computer(Output out)
{
this.out = out;
}
// 定义一个模拟获取字符串输入的方法
public void keyIn(String msg)
{
out.getData(msg);
}
// 定义一个模拟打印的方法
public void print()
{
out.out();
}
public static void main(String[] args)
{
// 使用PrinterFactory子类来创建OutputFactory
OutputFactory of = new BetterPrinterFactory();
// 将Output对象传入,创建Computer对象
Computer c = new Computer(of.getOutput());
c.keyIn("aaa");
c.keyIn("bbb");
c.print();
}
}
然后是打印设备,分别为Printer类和BetterPrinter类:
设备统一接口:
public interface Output
{
// 接口里定义的属性只能是常量
int MAX_CACHE_LINE = 50;
// 接口里定义的只能是public的抽象实例方法
void out();
void getData(String msg);
}
Printer类:
// 让Printer类实现Output
public class Printer implements Output
{
private String[] printData = new String[MAX_CACHE_LINE];
// 用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
// 只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("打印机打印:" + printData[0]);
// 把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE)
{
System.out.println("输出队列已满,添加失败");
}
else
{
// 把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
BetterPrinter类:
public class BetterPrinter implements Output
{
private String[] printData = new String[MAX_CACHE_LINE * 2];
// 用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
// 只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("高速打印机正在打印:" + printData[0]);
// 把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE * 2)
{
System.out.println("输出队列已满,添加失败");
}
else
{
// 把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
}
}
产品类都已经建立好,进行创建工厂接口以及实现相应的工厂类:
工厂接口如下,这里的工厂接口只有一个getOutput接口,因为工厂方法模式中工厂只负责产品对象的创建,不涉及逻辑判断。
public interface OutputFactory
{
// 仅定义一个方法用于返回输出设备。
Output getOutput();
}
PrinterFactory:
public class PrinterFactory
implements OutputFactory
{
public Output getOutput()
{
// 该工厂只负责产生Printer对象
return new Printer();
}
}
BetterPrinterFactory:
public class BetterPrinterFactory
implements OutputFactory
{
public Output getOutput()
{
// 该工厂只负责产生BetterPrinter对象
return new BetterPrinter();
}
}
然后上面computer类中的main方法中进行逻辑判断,需要什么则访问什么工厂创建产品。这就是工厂方法模式的原理,与简单工厂模式不同的是将逻辑判断放入了客户端,而且简单工厂是一个工厂创建所有对象,而工厂方法每种对象都有一个工厂。工厂方法优点是客户端代码与被调用对象的实现类分离。缺点:客户端代码与不同工厂类存在耦合。