概括
工厂模式主要分三种,简单工厂,工厂方法,抽象工厂。
简单工厂
以生产linux、mac、windows系统的computer为例,简单工厂需要一个computer接口,不同的系统作为其实现类,然后通过一个工厂对象来生产computer,代码如下。
/**
* @author ctl
* @date 2021/1/10
*/
public interface Computer {
void create();
}
/**
* @author ctl
* @date 2021/1/10
*/
public class Mac implements Computer {
@Override
public void create() {
System.out.println("mac created");
}
}
/**
* @author ctl
* @date 2021/1/10
*/
public class Linux implements Computer{
@Override
public void create() {
System.out.println("linux created");
}
}
/**
* @author ctl
* @date 2021/1/10
*/
public class Windows implements Computer {
@Override
public void create() {
System.out.println("windows created");
}
}
/**
* @author ctl
* @date 2021/1/10
* 如果后续要添加种类,就要修改工厂类
*/
public class SimpleFactory {
public Computer createComputer(String type) {
if ("windows".equals(type)) {
return new Windows();
} else if ("mac".equals(type)) {
return new Mac();
} else if ("linux".equals(type)) {
return new Linux();
}
return null;
}
}
/**
* @author ctl
* @date 2021/1/10
*/
public class FactoryMain {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Computer computer = factory.createComputer("mac");
computer.create();
}
}
显然,使用简单工厂,如果想扩展,则需要修改工厂中的业务逻辑,违反来面向对象中的开闭原则。看下面一种修改后的实现。
工厂方法
UML
基于上述的computer和实现类,定义一个工厂接口,每个实现类对应一个实现工厂,代码如下。
工厂接口
/**
* @author ctl
* @date 2021/1/27
*/
public interface Factory {
Computer create();
}
/**
* @author ctl
* @date 2021/1/10
*/
public class LinuxFactory implements Factory {
@Override
public Computer create() {
return new Linux();
}
}
/**
* @author ctl
* @date 2021/1/10
*/
public class MacFactory implements Factory {
@Override
public Computer create() {
return new Mac();
}
}
/**
* @author ctl
* @date 2021/1/10
*/
public class WindowsFactory implements Factory {
@Override
public Computer create() {
return new Windows();
}
}
/**
* @author ctl
* @date 2021/1/10
* 跟简单工厂相比,若需扩展不用在工厂内部修改逻辑了,需要在客户端调用时指定工厂
*/
public class MethodMain {
public static void main(String[] args) {
MacFactory macFactory = new MacFactory();
Computer mac = macFactory.create();
LinuxFactory linuxFactory = new LinuxFactory();
Computer linux = linuxFactory.create();
mac.create();
linux.create();
}
}
工厂方法相对于简单工厂来说,想要扩展的话不用在工厂内部修改逻辑了,在客户端调用时指定工厂即可,将逻辑的修改由内部转移到了外部。但这种方法产品种类单一,如果是多种类的产品,就不太适用了。这时候就需要抽象工厂,看下面的实现方式。
抽象工厂
UML
上面用三种系统的电脑做示例,种类单一,这里我们换一个种类丰富的示例。
以生产鼠标和键盘为例,鼠标分别有蓝牙鼠标和usb连接的鼠标,键盘也是,代码如下。
抽象的键盘
/**
* @author ctl
* @date 2021/1/10
*/
public interface Keyboard {
void write();
}
蓝牙键盘
/**
* @author ctl
* @date 2021/1/10
*/
public class BlueToothKeyBoard implements Keyboard {
@Override
public void write() {
System.out.println("蓝牙键盘打字");
}
}
usb键盘
/**
* @author ctl
* @date 2021/1/10
*/
public class UsbKeyBoard implements Keyboard {
@Override
public void write() {
System.out.println("usb键盘打字");
}
}
抽象鼠标
/**
* @author ctl
* @date 2021/1/10
*/
public interface Mouse {
void click();
}
蓝牙鼠标
/**
* @author ctl
* @date 2021/1/10
*/
public class BlueToothMouse implements Mouse {
@Override
public void click() {
System.out.println("蓝牙鼠标点击");
}
}
usb鼠标
/**
* @author ctl
* @date 2021/1/10
*/
public class UsbMouse implements Mouse {
@Override
public void click() {
System.out.println("usb鼠标点击");
}
}
工厂接口,可以生产鼠标和键盘
/**
* @author ctl
* @date 2021/1/10
*/
public interface Factory {
Keyboard createKeyboard();
Mouse createMouse();
}
蓝牙工厂,生产蓝牙类型的鼠标和键盘
/**
* @author ctl
* @date 2021/1/10
*/
public class BlueToothFactory implements Factory {
@Override
public Keyboard createKeyboard() {
return new BlueToothKeyBoard();
}
@Override
public Mouse createMouse() {
return new BlueToothMouse();
}
}
usb工厂,生产usb类型的鼠标和键盘
/**
* @author ctl
* @date 2021/1/10
*/
public class UsbFactory implements Factory {
@Override
public Keyboard createKeyboard() {
return new UsbKeyBoard();
}
@Override
public Mouse createMouse() {
return new UsbMouse();
}
}
测试类
/**
* @author ctl
* @date 2021/1/10
* 适合于产品族概念的设计
*/
public class AbstMain {
public static void main(String[] args) {
Factory factory;
// 蓝牙设备工厂
factory = new BlueToothFactory();
Keyboard keyboard = factory.createKeyboard();
Mouse mouse = factory.createMouse();
keyboard.write();
mouse.click();
System.out.println("------------------------");
// usb设备工厂
factory = new UsbFactory();
Keyboard keyboard1 = factory.createKeyboard();
Mouse mouse1 = factory.createMouse();
keyboard1.write();
mouse1.click();
}
}
结果如下
抽象工厂更适用与拥有庞大而复杂的产品族的概念的时候,更换一个类型的工厂,即可更换该类型下的所有产品。
总结
常用的很多开源框架中都使用了工厂模式,如果在工作中纠结与使用哪种设计模式来实现业务逻辑,不妨平时多留意用到的一些框架中的设计模式。同时也要时刻记住一句话,不要为了设计而设计,切勿因过度设计与不合理设计,反而导致代码量剧增且不易读。