设计模式——抽象工厂模式
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
抽象工厂模式与工厂方法模式的区别
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。我们依然拿生产汽车的例子来说明他们之间的区别。
优点
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展,这真是抽象工厂模式的优点所在,然后抽象模式同时也存在不足的地方
缺点
抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则
实现
借助女娲造人的过程添加新的物种等级水果,然后根据地域造不同的人。类图如下:
人类接口:
package com.lidaming.design03.abstractfactory; public interface IHuman { void color(); }
人类的实现类:
package com.lidaming.design03.abstractfactory; public class WhiteHuman implements IHuman { public void color() { System.out.println("this is white"); } }
package com.lidaming.design03.abstractfactory; public class YellowHuman implements IHuman { public void color() { System.out.println("this is yellow"); } }
水果接口:
package com.lidaming.design03.abstractfactory; public interface IFruit { void locate(); }
水果的实现类:
package com.lidaming.design03.abstractfactory; public class Apple implements IFruit { public void locate() { System.out.println("grow on the tree"); } }
package com.lidaming.design03.abstractfactory; public class Orange implements IFruit { public void locate() { // TODO Auto-generated method stub System.out.println("grow on the tree"); } }
抽象工厂:
package com.lidaming.design03.abstractfactory; public interface AbstractFactory { IHuman createHuman(); IFruit createFruite(); }
具体工厂的实现:
package com.lidaming.design03.abstractfactory; public class AsiaFactory implements AbstractFactory { public IHuman createHuman() { try { return YellowHuman.class.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public IFruit createFruite() { try { return Apple.class.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
package com.lidaming.design03.abstractfactory; public class Europe implements AbstractFactory { public IHuman createHuman() { try { return WhiteHuman.class.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public IFruit createFruite() { try { return Orange.class.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
场景类:
package com.lidaming.design03.abstractfactory; public class Client { public static void main(String[] args) { AbstractFactory factory = new AsiaFactory(); IHuman human = factory.createHuman(); human.color(); IFruit fruit = factory.createFruite(); fruit.locate(); factory = new Europe(); human = factory.createHuman(); human.color(); fruit = factory.createFruite(); fruit.locate(); } }
分析
当抽象工厂面对扩展新的产品等级的时候,如:造动物的时候!
需要修改抽象工厂,具体工厂(违反“开放封闭原则”),至于维护成本,更是无法评估
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
参考:
http://blog.csdn.net/zhengzhb/article/details/7359385
http://blog.jobbole.com/78067/