工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,将对象的创建和使用分离,使得代码更具可维护性和可扩展性。常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式
简单工厂
违背开闭原则,简单工厂模式并不属于 GoF 23 种设计模式,但它是思想是工厂模式的基础。
需求描述
在一个图形绘制系统里,需要根据用户输入的形状类型(圆形、矩形、三角形)来创建相应的形状对象并绘制。简单工厂模式可将形状对象的创建逻辑封装在一个工厂类中。
// 抽象形状类
abstract class Shape {
public abstract void draw();
}
// 圆形类
class Circle extends Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 矩形类
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 三角形类
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("绘制三角形");
}
}
// 简单工厂类
class ShapeFactory {
public static Shape createShape(String shapeType) {
if ("Circle".equalsIgnoreCase(shapeType)) {
return new Circle();
} else if ("Rectangle".equalsIgnoreCase(shapeType)) {
return new Rectangle();
} else if ("Triangle".equalsIgnoreCase(shapeType)) {
return new Triangle();
}
return null;
}
}
// 客户端代码
public class SimpleFactoryExample {
public static void main(String[] args) {
Shape circle = ShapeFactory.createShape("Circle");
if (circle != null) {
circle.draw();
}
Shape rectangle = ShapeFactory.createShape("Rectangle");
if (rectangle != null) {
rectangle.draw();
}
Shape triangle = ShapeFactory.createShape("Triangle");
if (triangle != null) {
triangle.draw();
}
}
}
工厂方法模式
需求描述
在一个应用程序中,需要记录不同类型的日志,如文件日志、数据库日志。工厂方法模式可让每个具体的日志记录器都有对应的工厂类来创建。
// 抽象日志记录器类
abstract class Logger {
public abstract void log(String message);
}
// 文件日志记录器类
class FileLogger extends Logger {
@Override
public void log(String message) {
System.out.println("文件日志: " + message);
}
}
// 数据库日志记录器类
class DatabaseLogger extends Logger {
@Override
public void log(String message) {
System.out.println("数据库日志: " + message);
}
}
// 抽象工厂类
abstract class LoggerFactory {
public abstract Logger createLogger();
}
// 文件日志记录器工厂类
class FileLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
return new FileLogger();
}
}
// 数据库日志记录器工厂类
class DatabaseLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
return new DatabaseLogger();
}
}
// 客户端代码
public class FactoryMethodExample {
public static void main(String[] args) {
LoggerFactory fileLoggerFactory = new FileLoggerFactory();
Logger fileLogger = fileLoggerFactory.createLogger();
fileLogger.log("这是一条文件日志消息");
LoggerFactory databaseLoggerFactory = new DatabaseLoggerFactory();
Logger databaseLogger = databaseLoggerFactory.createLogger();
databaseLogger.log("这是一条数据库日志消息");
}
}
抽象工厂模式
需求描述
在一个跨平台的应用程序中,需要根据不同的操作系统(Windows、MacOS)创建不同风格的界面组件(按钮、文本框)。抽象工厂模式可以提供一个创建一系列相关或相互依赖对象的接口。
// 抽象按钮类
interface Button {
void click();
}
// Windows 按钮类
class WindowsButton implements Button {
@Override
public void click() {
System.out.println("Windows 按钮被点击");
}
}
// MacOS 按钮类
class MacOSButton implements Button {
@Override
public void click() {
System.out.println("MacOS 按钮被点击");
}
}
// 抽象文本框类
interface TextBox {
void inputText(String text);
}
// Windows 文本框类
class WindowsTextBox implements TextBox {
@Override
public void inputText(String text) {
System.out.println("Windows 文本框输入: " + text);
}
}
// MacOS 文本框类
class MacOSTextBox implements TextBox {
@Override
public void inputText(String text) {
System.out.println("MacOS 文本框输入: " + text);
}
}
// 抽象工厂类
interface GUIFactory {
Button createButton();
TextBox createTextBox();
// 这里还能横向拓展多个方法
// Select createSelect();
// TextArea createTextArea();
// Input createInput();
}
// Windows 工厂类
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextBox createTextBox() {
return new WindowsTextBox();
}
}
// MacOS 工厂类
class MacOSFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacOSButton();
}
@Override
public TextBox createTextBox() {
return new MacOSTextBox();
}
}
// 客户端代码
public class AbstractFactoryExample {
public static void main(String[] args) {
GUIFactory windowsFactory = new WindowsFactory();
Button windowsButton = windowsFactory.createButton();
TextBox windowsTextBox = windowsFactory.createTextBox();
windowsButton.click();
windowsTextBox.inputText("Hello from Windows!");
GUIFactory macosFactory = new MacOSFactory();
Button macosButton = macosFactory.createButton();
TextBox macosTextBox = macosFactory.createTextBox();
macosButton.click();
macosTextBox.inputText("Hello from MacOS!");
}
}
看到这里你可能工厂方法模式和抽象工厂模式觉得它俩很像?好像两种都能实现上面的例子?依旧区别不开???
好,那就再举个例子,让它们代码尽量一样,从中找不同
工厂方法
// 抽象产品
interface Product {
void use();
}
// 具体产品 A
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}
// 具体产品 B
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}
// 抽象工厂
abstract class Factory {
public abstract Product createProduct();
}
// 具体工厂 A,生产产品 A
class ConcreteFactoryA extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂 B,生产产品 B
class ConcreteFactoryB extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
// 客户端代码
public class FactoryMethodPatternDemo {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.use();
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.createProduct();
productB.use();
}
}
抽象工厂
// 抽象产品 A
interface ProductA {
void useA();
}
// 具体产品 A1
class ConcreteProductA1 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品 A1");
}
}
// 具体产品 A2
class ConcreteProductA2 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品 A2");
}
}
// 抽象产品 B
interface ProductB {
void useB();
}
// 具体产品 B1
class ConcreteProductB1 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品 B1");
}
}
// 具体产品 B2
class ConcreteProductB2 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品 B2");
}
}
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂 1,生产产品 A1 和产品 B1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂 2,生产产品 A2 和产品 B2
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
// 客户端代码
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.useA();
productB1.useB();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.useA();
productB2.useB();
}
}
看出区别了吗?
工厂方法模式的 Product A 和 B 之间从业务层面看,它俩没什么联系.
抽象工厂模式的 Product A 和 B 就有一种, 系列 1 的 A 产品 和 B 产品, 系列 2 的产品 A 和 B 的产品族的概念.
换个角度来理解上面抽象工厂模式的例子你可能更好的理解.
例如游戏装备中的套装概念
暗黑系套装的头盔(产品A1)和护腿(产品B1)
另一套是光明系的头盔(产品A2)和护腿(产品B2)
这俩者之间就有一个族的概念
如果这时候你出了一个武器(产品C), 这时候你需要再定义一个 ProductC, 然后有暗黑武器(产品C1)和光明武器(产品C2)两个具体产品类去实现 ProductC, 然后在工厂类 AbstractFactory 再去添加方法 createProductC(), 这样同一套创建出来的产品就会是一个套装,以后再增加DEFG…都可以继续扩展
以下是需要新增的代码
// 抽象产品 C - 武器
interface ProductC {
void useA();
}
// 具体产品 C1 - 暗黑系
class ConcreteProductC1 implements ProductC {
@Override
public void useA() {
System.out.println("使用产品 C1");
}
}
// 具体产品 C2 - 光明系
class ConcreteProductC2 implements ProductC {
@Override
public void useA() {
System.out.println("使用产品 C2");
}
}
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
// 然后抽象工厂则需要加创建C的方法
// ProductC createProductC();
}
应用场景
扩展性