当前位置:首页 > 技术知识 > 正文内容

架构师总结:掌握这7种设计模式,轻松应对99%Java 开发场景-工厂

maynowei5个月前 (09-29)技术知识94

引言:为什么是这7种模式?

在浩瀚的23种GoF设计模式中,这7种被精选出来,是因为它们覆盖了面向对象设计的核心原则(如SOLID),并解决了Java企业级开发中最常见、最棘手的几类问题:

  1. 对象创建与管理:如何优雅、灵活地创建对象?(单例、工厂、建造者)
  2. 接口兼容与适配:如何让不兼容的接口协同工作?(适配器)
  3. 行为变化与扩展:如何封装算法,使其独立于客户而变化?(策略)
  4. 对象间通信:如何建立对象间的松耦合通知机制?(观察者)
  5. 请求处理与分发:如何将请求的发送者和接收者解耦?(责任链)

掌握它们,就如同一位武士精通了七种核心剑技,足以应对绝大多数战斗场景。下面,我们开始逐一剖析。

模式二:工厂模式 - 对象创建的“流水线”

工厂模式是一个大家族,主要包括:简单工厂工厂方法抽象工厂。它们的目标都是解耦对象的创建和使用。

2.1 简单工厂(Simple Factory)

内容精讲:它不是一个标准的设计模式,更像是一种编程习惯。它提供一个创建对象的静态方法,根据传入的参数不同,返回不同的产品实例。

代码实现
假设我们有一个日志记录器(Logger)系统,可以记录到文件或数据库。

java

// 1. 产品接口
public interface Logger {
    void log(String message);
}

// 2. 具体产品
public class FileLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to FILE: " + message);
    }
}

public class DatabaseLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to DATABASE: " + message);
    }
}

// 3. 简单工厂
public class LoggerFactory {
    // 通常使用静态方法,因此也叫静态工厂
    public static Logger getLogger(String type) {
        if ("file".equalsIgnoreCase(type)) {
            return new FileLogger();
        } else if ("database".equalsIgnoreCase(type)) {
            return new DatabaseLogger();
        } else {
            throw new IllegalArgumentException("Invalid logger type: " + type);
        }
    }
}

// 4. 客户端使用
public class Client {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger("file");
        logger.log("This is a test message.");
    }
}

优缺点

  • 优点:客户端无需知道具体产品的类名,只需要知道参数即可。
  • 缺点:工厂职责过重,一旦需要增加新产品(如ConsoleLogger),就必须修改LoggerFactory的代码,违反了开闭原则

2.2 工厂方法模式(Factory Method)

内容精讲:定义一个用于创建对象的接口(工厂接口),但让子类决定实例化哪一个产品类。工厂方法使一个类的实例化延迟到其子类。

设计原则:依赖倒置原则(DIP)——客户端代码应该依赖抽象(工厂接口和产品接口),而不是具体实现。

代码实现
我们将简单工厂演进为工厂方法。

java

// 1. 产品接口 (不变)
public interface Logger {
    void log(String message);
}

// 2. 具体产品 (不变)
public class FileLogger implements Logger { ... }
public class DatabaseLogger implements Logger { ... }

// 3. 工厂接口
public interface LoggerFactory {
    Logger createLogger();
}

// 4. 具体工厂
public class FileLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可能包含复杂的初始化逻辑,如读取配置、创建文件等
        return new FileLogger();
    }
}

public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可能包含数据库连接等逻辑
        return new DatabaseLogger();
    }
}

// 5. 客户端使用
public class Client {
    public static void main(String[] args) {
        // 客户端依赖的是工厂接口和产品接口,与具体实现解耦
        LoggerFactory factory = new FileLoggerFactory(); // 可通过配置读取来决定用哪个工厂
        Logger logger = factory.createLogger();
        logger.log("This is a test message.");
    }
}

优缺点

  • 优点:完全符合开闭原则。要新增一个ConsoleLogger,只需要新增ConsoleLoggerConsoleLoggerFactory,无需修改任何现有代码。
  • 缺点:类的数量会增多,系统变得更抽象和复杂。

2.3 抽象工厂模式(Abstract Factory)

内容精讲:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。它处理的是“产品族”的概念。

何时使用:系统需要独立于其产品的创建、组合和表示时;系统需要配置多个产品系列中的一个时。

代码实现
假设我们的日志系统需要配套的连接器(Connector)来连接文件系统或数据库。

java

// 1. 抽象产品族A
public interface Logger {
    void log(String message);
}
// 2. 抽象产品族B
public interface Connector {
    void connect();
    void disconnect();
}

// 3. 具体产品族1: File系列
public class FileLogger implements Logger { ... }
public class FileConnector implements Connector {
    @Override
    public void connect() { System.out.println("Connected to File System."); }
    @Override
    public void disconnect() { System.out.println("Disconnected from File System."); }
}

// 4. 具体产品族2: Database系列
public class DatabaseLogger implements Logger { ... }
public class DatabaseConnector implements Connector {
    @Override
    public void connect() { System.out.println("Connected to Database."); }
    @Override
    public void disconnect() { System.out.println("Disconnected from Database."); }
}

// 5. 抽象工厂
public interface LoggerFactory {
    Logger createLogger();
    Connector createConnector(); // 创建配套的连接器
}

// 6. 具体工厂
public class FileLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        return new FileLogger();
    }
    @Override
    public Connector createConnector() {
        return new FileConnector();
    }
}

public class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        return new DatabaseLogger();
    }
    @Override
    public Connector createConnector() {
        return new DatabaseConnector();
    }
}

// 7. 客户端使用
public class Client {
    public static void main(String[] args) {
        LoggerFactory factory = new DatabaseLoggerFactory(); // 一整套Database产品族

        Connector connector = factory.createConnector();
        connector.connect();

        Logger logger = factory.createLogger();
        logger.log("Log after connection.");

        connector.disconnect();
    }
}

优缺点

  • 优点:保证客户端始终只使用同一个产品族中的对象;易于交换产品系列(只需更换具体工厂);符合开闭原则(新增产品族容易)和单一职责原则。
  • 缺点:难以支持新增产品等级结构(即新增一个产品类型,比如新增一个Monitor产品)。如果需要在抽象工厂中增加一个createMonitor()方法,那么所有具体工厂都需要修改,违反了开闭原则。

2.4 工厂模式总结

  • 简单工厂:静态方法,根据参数创建对象。违反开闭原则,适用于对象种类较少且固定的场景。
  • 工厂方法:针对一个产品等级结构。将创建逻辑推迟到子类,完全符合开闭原则。
  • 抽象工厂:针对多个产品等级结构(产品族)。强调一系列相关产品的创建,开闭原则倾向于“对扩展开放(新增产品族),对修改关闭”,但扩展新产品类型困难。

相关文章

惊现!iOS 16.5 kfd 漏洞利用,成功隐藏 Dock 栏

最近!kfd漏洞比较活跃,进展也是很顺利,今天就有大神成功使用 kfd 漏洞实现隐藏 Dock 栏,到底怎么回事?请继续往下看。-- kfd 漏洞说明 --kfd漏洞适合在 iOS 16.2 - 16...

C++并发同步核心-mutex深度解析:守护共享数据的关键

在多线程编程中,当多个线程需要访问和修改共享数据时,如果没有任何同步机制,就可能发生数据竞争(Data Race),导致程序行为不可预测、数据损坏甚至崩溃。C++标准库通过<mutex>头...

打通 JAVA 与内核系列之 一 ReentrantLock 锁的实现原理

写JAVA代码的同学都知道,JAVA里的锁有两大类,一类是synchronized锁,一类是concurrent包里的锁(JUC锁)。其中synchronized锁是JAVA语言层面提供的能力,在此不...

C++ 原子操作与锁的深度解析:为什么原子操作并非万金油?

大噶好,我是henry,今天来和大家浅浅聊一下为啥C++原子操作并非万能钥匙,原因有三,且听我娓娓道来:一、原子操作的线程安全性C++11 的 std::atomic 确实为单个变量的线程安全操作提供...

go语言并发原语RWMutex实现原理及闭坑指南

1.RWMutex常用方法Lock/UnlockRLock/RUnlockRLocker 为读操作返回一个Locker接 口的对象2. RWMutex使用方法 func main() { var c...

oracle和mysql的优缺点对比(oracle和mysql哪个简单)

oracle的优缺点优点:开放性:oracle 能所有主流平台上运行(包括 windows)完全支持所有工业标准采用完全开放策略使客户选择适合解决方案对开发商全力支持;可伸缩性,并行性:Oracle...