1.简单工厂模式:
简单工厂模式又称静态工厂方法模式。从命名上就可以看出这个模式一定很简单。它存
在的目的很简单:定义一个用于创建对象的接口。
先来看看它的组成:
//抽象产品角色 public interface Fruit { public void get(); } //具体产品角色 public class Apple implements Fruit { public void get() { System.out.println("采摘苹果"); } } public class Banana implements Fruit { public void get() { System.out.println("采摘香蕉"); } }
//工厂类角色 public class FruitFactory { public static Fruit getFruit(String type) throws InstantiationException, IllegalAccessException {//工厂方法.注意返回类型为抽象产品角色 // if(type.equalsIgnoreCase("apple")) // { // return Apple.class.newInstance(); // } // else if(type.equalsIgnoreCase("banana")) // { // return Banana.class.newInstance(); // } try { Class fruit=Class.forName(type);//type需要类名的全路径 return (Fruit) fruit.newInstance(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("找不到相应的实例化类"); return null; } }
public class MainClass { /** * @param args * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws InstantiationException, IllegalAccessException { // TODO Auto-generated method stub //简单工厂模式 // Fruit apple=FruitFactory.getFruit("apple"); // apple.get(); // Fruit banana=FruitFactory.getFruit("banana"); // banana.get(); Fruit apple=FruitFactory.getFruit("design.pattern.simplefactory.Apple");//注意是全路径 apple.get(); Fruit banana=FruitFactory.getFruit("design.pattern.simplefactory.Banana"); banana.get(); } }
2.工厂方法模式:
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这
样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分
担。
//抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。 //抽象工厂角色 public interface FruitFactoryInterface { public Fruit getFruit(); } public class OrangeFactory implements FruitFactoryInterface { @Override public Fruit getFruit() { // TODO Auto-generated method stub return new Orange(); } } public class PearFactory implements FruitFactoryInterface { @Override public Fruit getFruit() { // TODO Auto-generated method stub return new Pear(); } } //应该和具体产品形成对应关系... public class MainClass { /** * @param args * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws InstantiationException, IllegalAccessException { // TODO Auto-generated method stub FruitFactoryInterface ffi_0=new PearFactory();//工厂方法模式 Fruit pear=ffi_0.getFruit(); pear.get(); FruitFactoryInterface ffi_1=new OrangeFactory(); Fruit orange=ffi_1.getFruit(); orange.get(); } }
缺点
可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。
解决办法
为了避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
简单工厂模式与工厂方法模式真正的避免了代码的改动了?
没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。
面对这种情况,Java 的反射机制与配置文件的巧妙结合突破了限制——这在Spring 中完美的体现了出来。
小结
工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽
象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情
况下你可以考虑使用工厂方法模式:
1) 当客户程序不需要知道要使用对象的创建过程。
2) 客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
3.抽象工厂模式
先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。
还是让我们用一个例子来形象地说明一下吧。
例子中的NorthFruit 和SouthFruit 就是两个产品树(产品层次结构);而如图所示的
NorthGrape 和NorthPine 就是一个产品族。他们都可以放到水果家族中,因此功能
有所关联。同理SouthGrape 和SouthPine 也是一个产品族。
可以说,抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且
抽象工厂模式是三个里面最为抽象、最具一般性的。
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象
而且使用抽象工厂模式还要满足一下条件:
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
//抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。 //抽象工厂角色 public interface AbFruitFactory { public Fruit getGrape(); public Fruit getPine(); }
public class NorthFruitFactory implements AbFruitFactory {//具体工厂角色 @Override public Fruit getGrape() { // TODO Auto-generated method stub return new NorthGrape(); } @Override public Fruit getPine() { // TODO Auto-generated method stub return new NorthPine(); } }
public class SouthFruitFactory implements AbFruitFactory { @Override public Fruit getGrape() { // TODO Auto-generated method stub return new SouthGrape(); } @Override public Fruit getPine() { // TODO Auto-generated method stub return new SouthPine(); } }
public class MainClass { /** * @param args * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws InstantiationException, IllegalAccessException { // TODO Auto-generated method stub AbFruitFactory Abff_0=new NorthFruitFactory();//抽象工厂方法 Fruit grape_N=Abff_0.getGrape(); grape_N.get(); AbFruitFactory Abff_1=new SouthFruitFactory(); Fruit grape_S=Abff_1.getGrape(); grape_S.get(); Fruit pine_N=Abff_0.getPine(); pine_N.get(); Fruit pine_S=Abff_1.getPine(); pine_S.get(); } }