作者: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 换数据库只需换方言和驱动就可以切换不同数据库,也是利用了工厂模式。