快速了解工厂模式

简单工厂模式(JAVA描述)

    简单工厂模式要基于面象对象继承与多态的特性,应用接口编程实现。

    所谓模式是对经常遇到的软件设计问题形成的有效的通用的解决方案,是对特定问题的固定思维。

      有这样一个场景,假设程序中有一个Computer类需要组合(接上)一个输出打印设备,输出打印设备是多种类型的,现在有两个选择:直接让Computer类组合一个Printer,或者让Computer类组合一个Output,哪种好呢?

假设让Computer类组合一个Printer对象,如果有一天系统需要重构,需要使用BetterPrinter来代替Printer,这就需要修改Computer的源代码进行修改。如果系统中只有一个Computer类组合了Printer还好,但如果系统中有100个类组合了Printer,甚至10000个,那意味着需要打开1000个类进行修改。工作量无比大。

      为了避免这个问题,工厂模式建议让Computer类组合一个Output类型对象,将Computer类与Printer类完全分离。Computer对象实际组合的是Printer对象还是BetterPrinter对象,对Computer而言完全透明。当Printer对象切换到BetterPrinter对象时,系统完全一不爱影响。
    下面代码清单是这个Computer的定义

public class Computer {

	private Output out = new OutputFacotry().getOutput;
	public Computer(Output out)
	{
		this.out=out;
	}
	
	//模拟获取字符串输入的方法
	public void keyIn(String msg)
	{
		out.getData(msg);
	}
	
	public void printConter()
	{
		out.out();
	}
}
上面的Computer类已经完全与Printer类分离,只是与Output接口耦合。Computer不再负责创建Outerput对象,系统提供一个Output工厂来负责生成Output对象。下如是Output工厂的代码清单:

public class OutputFactory {
	public Output getOutput()
	{
	return new Printer();

Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
	}

	public static void main(String() args)
	{
	OutputFactory of =new OutputFacotry();
	Computer c = new Computer(of.geOutput());
	c.keyIn("这是要打印输出的信息")
	c.keyIn("打印输出的信息2")
	c.print();
	}
}

    在该OutputFactory类中包含一个getOutput()方法,该方法返回一个Output实现类的实例,该方法负责创建Output实例,具体创建哪个实例对象由该方法决定。如果系统需要将Printer改为BetterPrinter实现类,只需让BetterPrinter实现Output接口,并改变OutputFactory类中的getOutput()方法即可。

     下面是接口Output代码,定义了两上普通方法out()getData()及两个默认方法。


public interface Output {
	int MAX_CACHE_LINE=50;

	void out();
	void getData(String msg);
	default void print(String  msgs)
	{
	  for(String msg:msgs)
	  {
	    System.out.println(msg);
	  }
	 
	}

	default void test()
	  { 
	     System.out.println("默认的test()方法");
	  } 
}

     下面是BetterPrinter实现类的代码,BetterPrinter只是对原有的Printer进行简单修改,以模拟系统重构后的改进。


public class BetterPrinter implements Output {

	@Override
	public void out() {
		// TODO 自动生成的方法存根
		while(dataNum)>0
	       {
	            System.out.println("xxxxxx")
		    System.array(prinData,1,printData,0,--dataNum)
	        }

	}

	@Override
	public void getData(String msg) {
		// TODO 自动生成的方法存根
		if(dataNum>=MAX_CACHE_LINE*2)
        {
            System.out.println("输出队列已满,添加失败")
         }
	else
	{
		//把打印数据 添加 到队列里,已保存数据的数量 加1
		printData(dataNumm++)==msg
	}
	}

}

上面的BetterPrinter类也实现了Output接口,因此也可当成Output对象使用,于是只要把OutputFactory工厂类的getOutput()方法中粗体部分改为如下代码;

return new BetterPrinter();

 再次运行前面的OutputFactory.java程序,发现系统运行已经改为BetterPrinter对象,而不再是原来的Printer对象。

   通过这种方式,即可把所有生成Output对象的逻辑集中在OutputFactory工厂类中管理,而所有需要使用Output对象的类只需与Outpput 接口耦合,而不是与具体的类耦合。即使系统中很多类使用了Printer对象,只要OutputFactory类的getOutput()方法生成的Output对象是BetterPrinter对象,则它们全部都会改为使用BetterPrinter对象,而所有的程序无须修改,只需修改OutputFactory工厂类的getOutput()方法即可。

已上是简单工厂模式的JAVA实现。

如果OutputFactory抽象化。

Public interface OutputFactory

{

    Output getPrintOutput()

   

 

OutputgetStoreOutput();

   

……………………

}  就成为抽象工厂模式。

抽象工厂

    采用不同的工厂现生产不同的产品,则是抽象工厂模式(Abstractfactory)或工厂方法。抽象工厂别我叫Kit

    目的:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

   使用场合:在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,往往存在着更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?这就是我们要说的抽象工厂模式。其意图是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    优点

    1)分离了具体的类:

  抽象工厂模式帮助你控制一个应用创建的对象的类,因为一个工厂封装创建产品对象的责任和过程。它将客户和类的实现分离,客户通过他们的抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。

         2)使产品系列容易交换:

只要更换相应的具体工厂即可(经常用工厂方法来实现)。而一个抽象工厂创建了一个完整的产品系列,所以具体工厂变换后,整个产品系列会立刻改变。

    3)有利于产品的一致性:

当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而AbstractFactory很容易实现这一点。

    缺点

难以支持新产品的类型:

如果抽象工厂的基类要发生变化,那么针对每个产品系列的具体工厂也都要发生变化,显然这是很麻烦的。

不能创建有着不同个数对象的系列。

    注:

   抽象工厂模式主要在于应对“新系列”的需求变化。其缺点在于难于应付“新对象”的需求变动。如果在开发中出现了新对象,该如何去解决呢?这个问题并没有一个好的答案。

GOF《设计模式》中提出过一种解决方法,即给创建对象的操作增加参数,但这种做法并不能令人满意。事实上,对于新系列加新对象,就我所知,目前还没有完美的做法,只有一些演化的思路,这种变化实在是太剧烈了,因为系统对于新的对象是完全陌生的。” 

猜你喜欢

转载自blog.csdn.net/lixuezhi/article/details/80308339
今日推荐