工厂模式
概念
创建对象的过程与使用对象的过程分离
工厂模式是 Java 中最常用的创建型设计模式之一。它的核心思想是:将对象的创建与使用分离,通过一个"工厂"类来负责创建对象,而不是在客户端代码中直接使用 new 关键字。这样做可以降低耦合,提高代码的可维护性和扩展性。
简单工厂模式
简单工厂模式不是一个正式的设计模式,但它是工厂模式的基础。它通过一个工厂类,根据传入的参数决定创建哪种具体产品类的实例。
例如下面的代码,创建不同类型的日志记录器(文件日志、数据库日志),客户端传入的是 file 就调用 FileLogger() ,传入的是 db 就调用DatabaseLogger()。此时客户端无需知道具体产品类名,只需传入参数即可得到所需对象。
java
// 抽象产品
public interface Logger {
void log(String message);
}
// 具体产品1:文件日志
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("写入文件:" + message);
}
}
// 具体产品2:数据库日志
public class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("写入数据库:" + message);
}
}
// 工厂类
public class LoggerFactory {
public static Logger getLogger(String type) {
if ("file".equalsIgnoreCase(type)) {
return new FileLogger();
} else if ("db".equalsIgnoreCase(type)) {
return new DatabaseLogger();
} else {
throw new IllegalArgumentException("未知日志类型");
}
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("file");
logger.log("Hello World");
}
}
工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化延迟到子类。
java
// 抽象产品
public interface Logger {
void log(String message);
}
// 具体产品
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("写入文件:" + message);
}
}
public class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("写入数据库:" + message);
}
}
// 抽象工厂
public abstract class LoggerFactory {
// 工厂方法
public abstract Logger createLogger();
// 也可以包含其他业务方法,比如记录日志
public void log(String message) {
Logger logger = createLogger();
logger.log(message);
}
}
// 具体工厂1:文件日志工厂
public class FileLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
// 可以在这里添加创建文件日志的复杂逻辑
return new FileLogger();
}
}
// 具体工厂2:数据库日志工厂
public class DatabaseLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
// 可以在这里添加创建数据库日志的复杂逻辑
return new DatabaseLogger();
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
LoggerFactory factory = new FileLoggerFactory();
factory.log("Hello World");
factory = new DatabaseLoggerFactory();
factory.log("Hello Database");
}
}
抽象工厂模式
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。它通常用于产品族(一组具有相同主题的产品)的创建。
假设要开发一个跨平台的 UI 组件库,支持 Windows 和 Mac 风格
java
// 抽象产品:按钮
public interface Button {
void paint();
}
// 抽象产品:文本框
public interface TextField {
void display();
}
// 具体产品:Windows 按钮
public class WindowsButton implements Button {
@Override
public void paint() {
System.out.println("渲染 Windows 风格按钮");
}
}
// 具体产品:Mac 按钮
public class MacButton implements Button {
@Override
public void paint() {
System.out.println("渲染 Mac 风格按钮");
}
}
// 具体产品:Windows 文本框
public class WindowsTextField implements TextField {
@Override
public void display() {
System.out.println("显示 Windows 风格文本框");
}
}
// 具体产品:Mac 文本框
public class MacTextField implements TextField {
@Override
public void display() {
System.out.println("显示 Mac 风格文本框");
}
}
// 抽象工厂
public interface GUIFactory {
Button createButton();
TextField createTextField();
}
// 具体工厂:Windows 风格工厂
public class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
}
// 具体工厂:Mac 风格工厂
public class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
}
// 客户端使用
public class Application {
private Button button;
private TextField textField;
public Application(GUIFactory factory) {
button = factory.createButton();
textField = factory.createTextField();
}
public void render() {
button.paint();
textField.display();
}
public static void main(String[] args) {
// 根据操作系统或其他配置选择具体工厂
String os = "Windows"; // 假设从配置读取
GUIFactory factory;
if ("Windows".equalsIgnoreCase(os)) {
factory = new WindowsFactory();
} else {
factory = new MacFactory();
}
Application app = new Application(factory);
app.render();
}
}