设计模式之抽象工厂模式

        工厂方法模式一文中提到工厂方法模式的缺点很明显,就是客户端与工厂类之间的耦合,而且如果有无数工厂类,那么便会出现原问题,耦合严重。现在引入抽象工厂,就是为了将客户端与工厂类分离,采用简单工厂模式的思路,再建立一个工厂类,不过这个工厂类是工厂的工厂。这样就可以让客户端的代码与被调用的对象以及工厂类分离,降低耦合。

         本文仍然是电脑连接打印设备的例子。首先对于先建立一个打印设备的接口,所有打印设备都实现该接口,然后建立一个工厂接口,再针对不同打印设备相应的工厂并实现接口,工厂只负责相应产品的创建;接着建立一个工厂的工厂,负责逻辑判断实现工厂与客户端的解耦。

首先是输出设备接口:

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实例的调用。










评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值