`
anysky131
  • 浏览: 172052 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

简单工厂、工厂方法、抽象工厂

阅读更多
简单工厂(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();
	}
 
}



总结
简单工厂,方法工厂和抽象工厂没有优劣之分,只有不同的应用场景而已:
  如果产品的种类是不变的,只是想隐藏产品的实例化过程和具体的产品,就可以用简单工厂,也就是没有啥是变化的。
  如果产品种类是不定的,是变化的,如果很多的话,若用简单工厂的话,简单工厂的维护就会变大,而且会对已有类产生影响(原先的代码都会因为简单工厂类的修改而重新测试)。而且传入简单工厂的参数与产品没有明确的对应,维护起来不好。在这种场景下就可以用方法工厂,对新增产品只要增加新的工厂,在新的调用方调用相应工厂就OK了,可以完全解决上面的问题。
  抽象工厂处理的场景是,产品是分代的,且每个工厂都不止生产一种类型的产品(如青铜器兵工厂生产青铜刀和青铜剑,铁兵工厂生厂铁刀和铁剑),如果工厂都生产一种类型(具体点就是功用啥几乎都不一样,在类中表现为不同接口)的产品,就退化为方法工厂了。个人感觉,方法工厂就是抽象工厂的一个特例。



工厂模式也用了不少,特别是MS的petshop中对数据库的访问,通过工厂模式可以达到自由切换SQL 和 Oracle 数据库。近来也在看设计模式的书,发现工厂模式还是有不少的扩展。结合书中的知识和我自己理解,从代码的角度来比较工厂模式各变种。

1:简单工厂模式:其作用是实例化对象而不需要客户了解这个对象属于那个具体的子类。
using System;
using System.Collections;

public class MyClass
{
    public static void Main()
    {
        //通过参数来实例化子类。
        IVehicle vehicle = FactoryVehicle.CreateVehicle("car");
        vehicle.go();
        Console.ReadLine();    
    }
    
}

public class FactoryVehicle
{
    public static IVehicle CreateVehicle(string VehicleName)
    {
        switch(VehicleName.ToLower())
        {
            case "car":
            return new Car();
            case "boat":
            return new Boat();
            default:
            return new Car();
            
        }
    }

}
public interface IVehicle
{
    void go();
}
public class Car:IVehicle
{
    public void go()
    {
        Console.WriteLine("car");
    }
}
public class Boat:IVehicle
{
    public void go()
    {
        Console.WriteLine("boat");
    }
}


2:抽象工厂:即将工厂方法也抽象出来,由具体的子类来实例化工厂。产品创建部分和简单工厂模式相同。
using System;
using System.Collections;

public class MyClass
{
    public static void Main()
    {
        //通过定义的工厂来实例化。弊端是当产品很多时需要增加很多的工厂。代码重复。
        FactoryVehicle factory = new FactoryCar();
        IVehicle vehicle = factory.CreateVehicle();
        vehicle.go();
        Console.ReadLine();    
    }
    
}


public interface FactoryVehicle
{
     IVehicle CreateVehicle();

}

public class FactoryCar:FactoryVehicle
{
    public IVehicle CreateVehicle()
    {
        return new Car();
    }
}

public class FactoryBoat:FactoryVehicle
{
    public IVehicle CreateVehicle()
    {
        return new Boat();
    }
}

public interface IVehicle
{
    void go();
}

public class Car:IVehicle
{
    public void go()
    {
        Console.WriteLine("car");
    }
}

public class Boat:IVehicle
{
    public void go()
    {
        Console.WriteLine("boat");
    }
}



3:反射工厂模式: 其实就是通过反射的方式来获得具体实例化是那个类。
using System;
using System.Collections;
using System.Reflection;

public class MyClass
{
    public static void Main()
    {
        //使用反射的方法获得实例化的类
        IVehicle vechicle = ReflectFactory.CreateVehicleByReflect("Car");
        vechicle.go();
        Console.ReadLine();    
        
    }
    
}

public class ReflectFactory
{
    public static IVehicle CreateVehicleByReflect(string typeName)
    {
        Type type = Type.GetType(typeName);
        ConstructorInfo  ci = type.GetConstructor(System.Type.EmptyTypes);;
        return (IVehicle)ci.Invoke(null);
    }
}
public class FactoryBoat:FactoryVehicle
{
    public IVehicle CreateVehicle()
    {
        return new Boat();
    }
}

public class FactoryCar:FactoryVehicle
{
    public IVehicle CreateVehicle()
    {
        return new Car();
    }
}

public interface FactoryVehicle
{
    IVehicle CreateVehicle();

}
public interface IVehicle
{
    void go();
}

public class Car:IVehicle
{
    public void go()
    {
        Console.WriteLine("car");
    }
}

public class Boat:IVehicle
{
    public void go()
    {
        Console.WriteLine("boat");
    }
}

分享到:
评论
1 楼 feverbit 2008-09-01  
3种工厂模式就是从各个层次上来解耦~

相关推荐

Global site tag (gtag.js) - Google Analytics