简单工厂(Simple Factory Pattern)
简单工厂模式,把对象(统一接口)的创建封装起来,而不去用了解对象所代表的真正的实现类及其初始化过程。我们只需要把参数传递给简单工厂,工厂就会根据你的需要返回相应的产品对象。示例代码如下:
|
Iproduct.java
public interface IProduct
{
void work();
}
Product1.java
public class Product1 implements IProduct
{
@Override
public void work()
{
System.out.println(this.getClass().getSimpleName());
}
}
Product2.java
public class Product2 implements IProduct
{
@Override
public void work()
{
System.out.println(this.getClass().getSimpleName());
}
}
SimpleFactory.java
public class SimpleFactory
{
public IProduct newProduct(String strcase)
{
IProduct pro = null;
if(strcase.equals("product1"))
{
pro = new Product1();
}
else
{
if(strcase.equals("product2"))
{
pro = new Product2();
}
}
return pro;
}
}
SimpleFactoryApp.java
public class SimpleFactoryApp
{
public static void main(String[] args)
{
IFactory factory = new SimpleFactory();
IProduct pro1 = factory.newProduct("product1");
IProduct pro2 = factory.newProduct("product2");
pro1.work();
pro2.work();
}
}
|
Product1和Product1都实现了Iproduct接口;在SimpleFactory的newProduct()方法中,根据传入的参数不同,我们实例化实现Iproduct接口的不同Product,并返回给调用方;而在SimpleFactoryApp中,我们不必知道factory是返回了哪一种Product,也不必知道他的创建过程,只知道它是一个Product,直接用就可以了。
这样做的好处就是把耦合放进了factory,调用方和product不再耦合,放在factory的原因也是因为调用方是多变的,而factory是固定的(相对而言),也就是说比如对Product1和Product2而言,车间A会用到,车间B也会用到,如果不用Factory的话,车间A和车间B的代码就会和Product1和Product2耦合,如果现在要求根据调用方上下文改变,如果车间A只能用Product1,车间B只能用Product2,那么我们要同时修改车间A和车间B的代码,或者有更多的车间需要处理呢;如果有Factory的话呢,我只要在Factory中根据上下文来判断返回相应的Product就可以了。
方法工厂(Method Factory Pattern)
简单工厂模式把所有的重心放到工厂类上,一旦向系统增加新的产品,就必须修改工厂类,不满足开闭原则(对修改关闭,对扩展开放);工厂方法模式提供一个抽象的工厂接口,在不同的产品结构上实现不同的产品工厂具体类来创建该层次中的产品,通常一个具体工厂创建一个具体产品。在新增产品的时候,只需要实现新的对应工厂就可以满足需要,是符合开闭原则的。
示例代码如下:
|
Iproduct.java, Product1.java,Product2.java和上面的一样。
ImethodFactory.java
public interface IMethodFactory
{
IProduct newProduct();
}
MethodFactorySub1.java
public class MethodFactorySub1 implements IMethodFactory
{
@Override
public IProduct newProduct()
{
return new Product1();
}
}
MethodFactorySub2.java
public class MethodFactorySub2 implements IMethodFactory
{
@Override
public IProduct newProduct()
{
return new Product2();
}
}
MethodFactoryApp.java
public class MethodFactoryApp
{
/**
* @param args
*/
public static void main(String[] args)
{
IMethodFactory methodFactory1 = new MethodFactorySub1();
IMethodFactory methodFactory2 = new MethodFactorySub2();
IProduct pro1 = methodFactory1.newProduct();
IProduct pro2 = methodFactory2.newProduct();
pro1.work();
pro2.work();
}
}
|
对不同的产品的实例化,由不同的工厂来实现,每一种工厂都是生产特定的产品。
但是我有个疑问就是,虽然每个需要产品的调用方都不再和具体的产品耦合,但每一个都会和一个特定的工厂进行耦合。理解:每个调用方都仍不会受到产品耦合的关系,有工厂这一层次,让这种易变性仍然保持在工厂的层次。并且在新增Product和调用方的时候不会再影响到原先的工厂(简单工厂的话就要修改简单工厂类了),只需要增加新的工厂类并在新的调用方中调用新的工厂就可以了。
抽象工厂(abstract factory)
一个工厂有时不光生产一种产品,比如一个青铜器的兵工厂,可能不光生产青铜刀,还生产青铜剑,属于一个系列的产品。现在生产工艺升级,现在生产性能更好的铁刀,铁剑,原先的模具,融炉都不再适用,而且为了满足过渡需要,原先的工厂肯定也要保留,而且两个工厂有很多相似之处可以提取出来。两个工厂生产的产品也有很多相似之处,但一个工厂生产的不同产品的相同之处只在于他们用的生产工艺和处理过程是一样的,但产品本身是不同的。但在不同的工厂中,产品却有类似的,如青铜刀-铁刀,青铜剑-铁剑。
具体的工厂生产的是一个产品系列内的产品,不同工厂生产的是不同代的产品。
抽象工厂的UML类图大致类似上面,两个具体工厂都继承自统一的抽象工厂,抽象工厂生产一个系统的产品(即IProduct1 和IProduct2),两个具体工厂就生成具体系列的产品。
|
IAbstractFactory.java
public interface IAbstractFactory
{
IProduct1 getProduct1Instance();
IProduct2 getProduct2Instance();
}
ConcreteFactory1.java ConcreteFactory2和此类似
public class ConcreteFactory1 implements IAbstractFactory {
@Override
public IProduct1 getProduct1Instance()
{
// TODO Auto-generated method stub
return new Product11();
}
@Override
public IProduct2 getProduct2Instance()
{
// TODO Auto-generated method stub
return new Product21();
}
}
IProduct1.java IProduct2和此类似
public interface IProduct1
{
void dowork1();
}
Product11.java Product12、Product21、Product22和此类似
public class Product11 implements IProduct1 {
@Override
public void dowork1()
{
System.out.println(this.getClass().getSimpleName());
}
}
AbstractFactoryApp.java
public class AbstractFactoryApp {
/**
* @param args
*/
public static void main(String[] args)
{
IAbstractFactory factory1 = new ConcreteFactory1();
factory1.getProduct1Instance().dowork1();
factory1.getProduct2Instance().dowork2();
IAbstractFactory factory2 = new ConcreteFactory2();
factory2.getProduct1Instance().dowork1();
factory2.getProduct2Instance().dowork2();
}
} |