工厂方法模式一文中提到工厂方法模式的缺点很明显,就是客户端与工厂类之间的耦合,而且如果有无数工厂类,那么便会出现原问题,耦合严重。现在引入抽象工厂,就是为了将客户端与工厂类分离,采用简单工厂模式的思路,再建立一个工厂类,不过这个工厂类是工厂的工厂。这样就可以让客户端的代码与被调用的对象以及工厂类分离,降低耦合。
本文仍然是电脑连接打印设备的例子。首先对于先建立一个打印设备的接口,所有打印设备都实现该接口,然后建立一个工厂接口,再针对不同打印设备相应的工厂并实现接口,工厂只负责相应产品的创建;接着建立一个工厂的工厂,负责逻辑判断实现工厂与客户端的解耦。
首先是输出设备接口:
public interface Output
{
// 接口里定义的属性只能是常量
int MAX_CACHE_LINE = 50;
// 接口里定义的只能是public的抽象实例方法
void out();
void getData(String msg);
}
然后是实现产品类:
// 让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;
}
}
}
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;
}
}
}
接着是工厂接口,接口中只有一个方法,用于创建产品,所以每个工厂只负责相应产品对象的创建。
public interface OutputFactory
{
// 仅定义一个方法用于返回输出设备。
Output getOutput();
}
针对不同产品,建立相应的工厂,以下是两个工厂,每个工厂只负责创建自己相应的产品对象,无须进行逻辑判断。
public class PrinterFactory
implements OutputFactory
{
public Output getOutput()
{
// 该工厂只负责产生Printer对象
return new Printer();
}
}
public class BetterPrinterFactory
implements OutputFactory
{
public Output getOutput()
{
// 该工厂只负责产生BetterPrinter对象
return new BetterPrinter();
}
}
建立一个工厂的工厂,负责进行逻辑判断,根据不同情况,启动不同的工厂,从而创建不同的打印设备。
public class OutputFactoryFactory
{
// 仅定义一个方法用于返回输出设备。
public static OutputFactory getOutputFactory(
String type)
{
if (type.equalsIgnoreCase("better"))
{
return new BetterPrinterFactory();
}
else
{
return new PrinterFactory();
}
}
}
最后使用电脑连接打印:
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)
{
// 使用OutputFactoryFactory工厂类创建OutputFactory
OutputFactory of = OutputFactoryFactory
.getOutputFactory("better");
// 调用OuputFactory的方法获取Output对象,
// 并将Output对象传入,创建Computer对象
Computer c = new Computer(of.getOutput());
c.keyIn("a");
c.keyIn("b");
c.print();
}
} 这样,整个过程下来,客户端与被调用对象以及工厂类实现完全的解耦,只需要修改抽象工厂以及相应的类即可。
简单工厂模式、工厂方法模式两篇分别讲了简单工厂模式和工厂方法模式,与本文的抽象工厂模式,其实也算是一母同胞,都是为了将调用者与被调用者分离解耦。其实抽象工厂模式是在前两个模式基础上的改进,它综合了简单工厂模式和工厂方法模式。
1.简单工厂模式是将产品交给工厂创建,但是这个工厂需要做的事情太多了,既要创建所有对象,又要进行逻辑判断;并且有时产品类比较多,会造成工厂类代码臃肿,逻辑关系复杂。
2.工厂方法模式则是为每种产品都设计了一个工厂,在客户端进行对工厂的创建,那么工厂就不需要进行逻辑判断,只需要进行产品对象的创建,这样调用者与被调用的对象完全分离。
3.抽象工厂模式,则为了减轻工厂的工作量,将工厂进一步细化,为每一类产品设计一个工厂,然而又想将调用者以及产品类、工厂类分离出来,就采用了简单工厂模式的思路,将工厂又想象成一种产品,建立工厂的工厂,其实这就是一种迭代,直到最后抽象工厂的逻辑比较清晰,并且能将调用者与其他类分离解耦。
Spring容器就是一个大工厂,用于创建各种Bean实例,并且通过Spring管理各种Bean实例的调用。

438

被折叠的 条评论
为什么被折叠?



