设计模式学习(三):工厂模式
作者:Grey
原文地址:
工厂模式
工厂模式是创建型模式,工厂模式分为:简单工厂,工厂方法和抽象工厂三种类型。
简单工厂
这个模式很简单,比如我们需要制造不同类型的鼠标,我们只需要创建一个鼠标工厂
public class MouseFactory { public static Mouse createMouse(int type) { switch (type) { case 1: return new HpMouse(); case 2: return new LenovoMouse(); case 0: default: return new DellMouse(); } } public static void main(String[] args) { Mouse mouse = MouseFactory.createMouse(1); mouse.sayHi(); } }
根据不同的 type 来创建不同的鼠标即可。这个模式的缺点很明显,违反了开闭原则 ,所以我们引入工厂方法
工厂方法
工厂方法中,我们可以定义对应产品的对应工厂,以上面这个鼠标的例子为例,我们可以增加工厂的接口
public interface MouseFactory { Mouse createMouse(); }
不同类型的鼠标工厂实现这个工厂即可,以 Dell 鼠标工厂为例
public class DellMouseFactory implements MouseFactory { @Override public Mouse createMouse() { return new DellMouse(); } }
主函数在调用的时候,直接指定工厂即可制造对应的产品了:
public class FactoryMethodDemo { public static void main(String[] args) { MouseFactory mf = new HpMouseFactory(); Mouse mouse = mf.createMouse(); mouse.sayHi(); } }
工厂方法的优点是符合开闭原则,但是缺点也很明显,就是在增加子类的时候,同时要增加一个子类的工厂,而且,只支持同一类产品的创建,不适用于同一产品族。
抽象工厂
举例,现在需要通过工厂来制造交通工具,如果是现代的工厂,制造的就是汽车,如果是古代的工厂,制造的就是马车, 我们可以先把工厂抽象出来,
public abstract class AbstractFactory { protected abstract Transportation createTransportation(); protected abstract WritingInstrument createWritingInstrument(); }
交通工具也可以抽象出来
public abstract class Transportation { protected abstract void go(); }
对于马车和汽车来说,只需要继承这个 Transportation 类,实现对应的 go 方法即可,以汽车为例
public class Car extends Transportation { @Override protected void go() { System.out.println("car go"); } }
对于现代工厂还是古代工厂,只需要继承 AbstractFactory 这个抽象类,实现 createTransportation 方法即可,以现代工厂为例
public class ModernFactory extends AbstractFactory { @Override protected Transportation createTransportation() { return new Car(); } @Override protected WritingInstrument createWritingInstrument() { return new Pen(); } }
主方法在调用的时候,只需要
public class Main { public static void main(String[] args) { AbstractFactory factory = new ModernFactory(); factory.createTransportation().go(); } }
抽象工厂的UML图如下:

Java SE 8 提供了 Supplier 这个函数式接口,我们可以通过这个接口很方便的实现工厂类。更多 Java SE 8 新特性见:Java SE 8 新增特性
举例:
我们可以定义一个 MovableFactory ,里面的 create 方法,传入的是一个 Supplier 对象,你可以把所有 Movable 的子类实现传给这个参数,示例如下:
public class MovableFactory { public static Movable create(Supplier<? extends Movable> supplier) { return supplier.get(); } public static void main(String[] args) { MovableFactory.create(Car::new).go(); MovableFactory.create(() -> new Ship()).go(); } }
工厂模式应用举例
-
JDK 中的 Calendar 类的 getInstance() 方法;
-
LogBack 中
LoggerFactory.getLogger()方法; -
在 Spring 中,所有工厂都是 BeanFactory 的子类。通过对 BeanFactory 的实现,我们可以从 Spring 的容器访问 Bean 。根据不同的策略调用 getBean() 方法,从而获得具体对象。
-
Hibernate 换数据库只需换方言和驱动就可以切换不同数据库,也是利用了工厂模式。