在面向对象编程中,最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说,许多类型对象的创造需要一系列的步骤:你可能需要计算或取得对象的初始设置;选择生成哪个子对象实例;或在生成你需要的对象之前必须先生成一些辅助功能的对象。工厂模式中,我们在创建对象时,不会对客户端暴露创建逻辑,只是提供一个公共接口来指向新创建的对象。
模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?
解决方案:建立一个工厂来创建对象
4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。
最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.
这就是工厂模式。
这里,只是对简单工厂和工厂模式进行详述,抽象工厂后边会陆续介绍。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
将简单工厂模式( Simple Factory )看为工厂方法模式的一种特例,两者归为一类。工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式,把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来,从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。 反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类,那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
总结:
( 1 )简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。 ( 2 )工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
对比下两者的UML类图:
(1)简单工厂模式
(2)工厂模式
public class Circle { public void draw() { System.out.println("Circle"); } } public class Rectangle { public void draw() { System.out.println("Rectangle"); } } public class MainTest { public static void main(String[] args) { Circle circle = new Circle(); circle.draw(); Rectangle rectangle = new Rectangle(); rectangle.draw(); } } 客户需要知道怎么去创建一款图形实体 , 客户和图形实体的创建就紧密耦合在一起了 . 为了降低耦合 , 就出现了工厂类 , 把创建图形实体的操作细节都放到了工厂里面去 , 客户直接使用工厂的创建工厂方法 , 传入想要的图形实体名称就行了 , 而不必去知道创建的细节 . 这就是工业革命了:简单工厂模式
产品类
public interface Shape { public void draw(); } public class Circle implements Shape{ @Override public void draw() { System.out.println("Circle"); } } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle"); } } public class Square implements Shape { @Override public void draw() { System.out.println("Square"); } } 工厂类
public class ShapeFactory { private Shape shape; public Shape getShape(String type){ switch (type) { case "Circle": shape = new Circle(); return shape; case "Square": shape = new Square(); return shape; case "Rectangle": shape = new Rectangle(); return shape; default: return null; } } } 客户类
public class MainTest { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); Shape circleShape = shapeFactory.getShape("Circle"); circleShape.draw(); } }
简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。 先来看看它的组成: 1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品 2)抽象产品角色:它一般是具体产品继承的父类或者实现的接口。 3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。
下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户想要一个多边形的产品时,此时,产品类的添加符合开闭原则,但是需要在工厂类中增加相应的创建业务逻辑(createBMW(inttype)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。 我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。 于是工厂方法模式作为救世主出现了。工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。产品类
public interface Shape { public void draw(); } public class Circle implements Shape{ @Override public void draw() { System.out.println("Circle"); } } public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle"); } } public class Square implements Shape { @Override public void draw() { System.out.println("Square"); } } 工厂类
public interface AbstractShapeFactory { public Shape create(); } public class RectangleFactory implements AbstractShapeFactory { @Override public Shape create() { return new Rectangle(); } } public class SquareFactory implements AbstractShapeFactory { @Override public Shape create() { // TODO Auto-generated method stub return new Square(); } } public class CircleFactory implements AbstractShapeFactory { @Override public Shape create() { // TODO Auto-generated method stub return new Circle(); } } 客户类
public class MainTest { public static void main(String[] args) { AbstractShapeFactory abstractShapeFactory = new RectangleFactory(); Shape circle = abstractShapeFactory.create(); circle.draw(); } } 可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情 况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实 现。
参考资料:http://blog.csdn.net/hguisu/article/details/7505909
http://www.runoob.com/design-pattern/factory-pattern.html