Java设计模式实战指南:让你的代码更优雅

设计模式是软件开发中经过时间考验的解决方案,它们代表了最佳实践,能够帮助我们写出更加可维护、可扩展和可重用的代码。本文将深入探讨Java开发中最常用的设计模式,并通过实际案例展示它们的应用场景。

什么是设计模式?

设计模式是在特定环境下,为解决某一通用软件设计问题提供的一套定制的解决方案。它不是代码,而是解决问题的思路和方法。设计模式的核心思想是”找出程序中变化的部分,并将变化封装起来”。

设计模式的三大类型

  1. 创建型模式 – 关注对象的创建过程
  2. 结构型模式 – 关注类和对象的组合
  3. 行为型模式 – 关注对象间的通信和责任分配

一、单例模式(Singleton Pattern)

应用场景

单例模式用于确保一个类只有一个实例,并提供全局访问点。常用于数据库连接池、日志记录器、配置管理器等场景。

实现方式

1. 饿汉式(线程安全)

public class EagerSingleton {
    // 类加载时就创建实例
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    
    private EagerSingleton() {
        // 私有构造函数
    }
    
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

2. 懒汉式(双重检查锁定)

public class LazySingleton {
    private static volatile LazySingleton instance;
    
    private LazySingleton() {}
    
    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

3. 枚举实现(推荐)

public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("执行业务逻辑");
    }
}

// 使用方式
EnumSingleton.INSTANCE.doSomething();

实际应用:数据库连接管理器

public class DatabaseManager {
    private static volatile DatabaseManager instance;
    private Connection connection;
    
    private DatabaseManager() {
        try {
            // 初始化数据库连接
            String url = "jdbc:mysql://localhost:3306/mydb";
            String username = "root";
            String password = "password";
            this.connection = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            throw new RuntimeException("数据库连接失败", e);
        }
    }
    
    public static DatabaseManager getInstance() {
        if (instance == null) {
            synchronized (DatabaseManager.class) {
                if (instance == null) {
                    instance = new DatabaseManager();
                }
            }
        }
        return instance;
    }
    
    public Connection getConnection() {
        return connection;
    }
}

二、工厂模式(Factory Pattern)

简单工厂模式

// 产品接口
interface Animal {
    void makeSound();
}

// 具体产品
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

// 简单工厂
class AnimalFactory {
    public static Animal createAnimal(String type) {
        switch (type.toLowerCase()) {
            case "dog":
                return new Dog();
            case "cat":
                return new Cat();
            default:
                throw new IllegalArgumentException("未知的动物类型: " + type);
        }
    }
}

// 使用示例
public class SimpleFactoryExample {
    public static void main(String[] args) {
        Animal dog = AnimalFactory.createAnimal("dog");
        Animal cat = AnimalFactory.createAnimal("cat");
        
        dog.makeSound(); // 输出: 汪汪汪
        cat.makeSound(); // 输出: 喵喵喵
    }
}

工厂方法模式

// 抽象工厂
abstract class AnimalFactory {
    public abstract Animal createAnimal();
    
    // 模板方法
    public void processAnimal() {
        Animal animal = createAnimal();
        animal.makeSound();
        System.out.println("动物处理完成");
    }
}

// 具体工厂
class DogFactory extends AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

class CatFactory extends AnimalFactory {
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

实际应用:支付方式工厂

// 支付接口
interface PaymentMethod {
    void pay(double amount);
}

// 具体支付方式
class AlipayPayment implements PaymentMethod {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付: ¥" + amount);
    }
}

class WeChatPayment implements PaymentMethod {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付: ¥" + amount);
    }
}

class CreditCardPayment implements PaymentMethod {
    @Override
    public void pay(double amount) {
        System.out.println("使用信用卡支付: ¥" + amount);
    }
}

// 支付工厂
class PaymentFactory {
    public static PaymentMethod createPayment(String type) {
        switch (type.toLowerCase()) {
            case "alipay":
                return new AlipayPayment();
            case "wechat":
                return new WeChatPayment();
            case "creditcard":
                return new CreditCardPayment();
            default:
                throw new IllegalArgumentException("不支持的支付方式: " + type);
        }
    }
}

三、观察者模式(Observer Pattern)

观察者模式定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知并自动更新。

基础实现

import java.util.*;

// 观察者接口
interface Observer {
    void update(String message);
}

// 被观察者接口
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

// 具体被观察者
class NewsPublisher implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String latestNews;
    
    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
    
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
    
    public void publishNews(String news) {
        this.latestNews = news;
        System.out.println("发布新闻: " + news);
        notifyObservers(news);
    }
}

// 具体观察者
class NewsSubscriber implements Observer {
    private String name;
    
    public NewsSubscriber(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        System.out.println(name + " 收到新闻推送: " + message);
    }
}

// 使用示例
public class ObserverPatternExample {
    public static void main(String[] args) {
        NewsPublisher publisher = new NewsPublisher();
        
        NewsSubscriber subscriber1 = new NewsSubscriber("张三");
        NewsSubscriber subscriber2 = new NewsSubscriber("李四");
        
        publisher.addObserver(subscriber1);
        publisher.addObserver(subscriber2);
        
        publisher.publishNews("重大科技突破!");
        // 输出:
        // 发布新闻: 重大科技突破!
        // 张三 收到新闻推送: 重大科技突破!
        // 李四 收到新闻推送: 重大科技突破!
    }
}

实际应用:股票价格监控系统

// 股票
class Stock {
    private String symbol;
    private double price;
    private List<StockObserver> observers = new ArrayList<>();
    
    public Stock(String symbol, double price) {
        this.symbol = symbol;
        this.price = price;
    }
    
    public void addObserver(StockObserver observer) {
        observers.add(observer);
    }
    
    public void removeObserver(StockObserver observer) {
        observers.remove(observer);
    }
    
    public void setPrice(double price) {
        double oldPrice = this.price;
        this.price = price;
        notifyObservers(oldPrice, price);
    }
    
    private void notifyObservers(double oldPrice, double newPrice) {
        for (StockObserver observer : observers) {
            observer.onPriceChanged(symbol, oldPrice, newPrice);
        }
    }
    
    // getters
    public String getSymbol() { return symbol; }
    public double getPrice() { return price; }
}

// 股票观察者
interface StockObserver {
    void onPriceChanged(String symbol, double oldPrice, double newPrice);
}

// 投资者
class Investor implements StockObserver {
    private String name;
    
    public Investor(String name) {
        this.name = name;
    }
    
    @Override
    public void onPriceChanged(String symbol, double oldPrice, double newPrice) {
        double changePercent = ((newPrice - oldPrice) / oldPrice) * 100;
        System.out.printf("%s 收到 %s 股票价格变动通知: %.2f -> %.2f (%.2f%%)\n", 
                         name, symbol, oldPrice, newPrice, changePercent);
        
        if (changePercent > 5) {
            System.out.println(name + " 决定卖出 " + symbol);
        } else if (changePercent < -5) {
            System.out.println(name + " 决定买入 " + symbol);
        }
    }
}

四、策略模式(Strategy Pattern)

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。

基础实现

// 策略接口
interface DiscountStrategy {
    double calculateDiscount(double originalPrice);
}

// 具体策略
class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculateDiscount(double originalPrice) {
        return originalPrice;
    }
}

class PercentageDiscountStrategy implements DiscountStrategy {
    private double percentage;
    
    public PercentageDiscountStrategy(double percentage) {
        this.percentage = percentage;
    }
    
    @Override
    public double calculateDiscount(double originalPrice) {
        return originalPrice * (1 - percentage / 100);
    }
}

class FixedAmountDiscountStrategy implements DiscountStrategy {
    private double discountAmount;
    
    public FixedAmountDiscountStrategy(double discountAmount) {
        this.discountAmount = discountAmount;
    }
    
    @Override
    public double calculateDiscount(double originalPrice) {
        return Math.max(0, originalPrice - discountAmount);
    }
}

// 上下文类
class ShoppingCart {
    private DiscountStrategy discountStrategy;
    private double totalAmount;
    
    public ShoppingCart() {
        this.discountStrategy = new NoDiscountStrategy();
    }
    
    public void setDiscountStrategy(DiscountStrategy strategy) {
        this.discountStrategy = strategy;
    }
    
    public void setTotalAmount(double amount) {
        this.totalAmount = amount;
    }
    
    public double getFinalPrice() {
        return discountStrategy.calculateDiscount(totalAmount);
    }
}

实际应用:排序算法选择器

import java.util.*;

// 排序策略接口
interface SortStrategy<T extends Comparable<T>> {
    void sort(List<T> list);
    String getAlgorithmName();
}

// 冒泡排序策略
class BubbleSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
    @Override
    public void sort(List<T> list) {
        int n = list.size();
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (list.get(j).compareTo(list.get(j + 1)) > 0) {
                    Collections.swap(list, j, j + 1);
                }
            }
        }
    }
    
    @Override
    public String getAlgorithmName() {
        return "冒泡排序";
    }
}

// 快速排序策略
class QuickSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
    @Override
    public void sort(List<T> list) {
        quickSort(list, 0, list.size() - 1);
    }
    
    private void quickSort(List<T> list, int low, int high) {
        if (low < high) {
            int pi = partition(list, low, high);
            quickSort(list, low, pi - 1);
            quickSort(list, pi + 1, high);
        }
    }
    
    private int partition(List<T> list, int low, int high) {
        T pivot = list.get(high);
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            if (list.get(j).compareTo(pivot) <= 0) {
                i++;
                Collections.swap(list, i, j);
            }
        }
        Collections.swap(list, i + 1, high);
        return i + 1;
    }
    
    @Override
    public String getAlgorithmName() {
        return "快速排序";
    }
}

// 排序器上下文
class Sorter<T extends Comparable<T>> {
    private SortStrategy<T> strategy;
    
    public void setStrategy(SortStrategy<T> strategy) {
        this.strategy = strategy;
    }
    
    public void sort(List<T> list) {
        if (strategy == null) {
            throw new IllegalStateException("排序策略未设置");
        }
        
        long startTime = System.nanoTime();
        strategy.sort(list);
        long endTime = System.nanoTime();
        
        System.out.printf("使用 %s 完成排序,耗时: %.2f ms\n", 
                         strategy.getAlgorithmName(), 
                         (endTime - startTime) / 1_000_000.0);
    }
    
    // 根据数据量自动选择最优策略
    public void smartSort(List<T> list) {
        if (list.size() < 50) {
            setStrategy(new BubbleSortStrategy<>());
        } else {
            setStrategy(new QuickSortStrategy<>());
        }
        sort(list);
    }
}

五、装饰器模式(Decorator Pattern)

装饰器模式允许向一个现有的对象添加新功能,同时又不改变其结构。

实际应用:咖啡订单系统

// 饮料接口
interface Beverage {
    String getDescription();
    double getCost();
}

// 基础饮料
class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return "意式浓缩咖啡";
    }
    
    @Override
    public double getCost() {
        return 25.0;
    }
}

class HouseBlend implements Beverage {
    @Override
    public String getDescription() {
        return "招牌咖啡";
    }
    
    @Override
    public double getCost() {
        return 20.0;
    }
}

// 装饰器基类
abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
    
    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}

// 具体装饰器
class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + " + 牛奶";
    }
    
    @Override
    public double getCost() {
        return beverage.getCost() + 3.0;
    }
}

class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        super(beverage);
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + " + 摩卡";
    }
    
    @Override
    public double getCost() {
        return beverage.getCost() + 5.0;
    }
}

class WhippedCream extends CondimentDecorator {
    public WhippedCream(Beverage beverage) {
        super(beverage);
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + " + 奶泡";
    }
    
    @Override
    public double getCost() {
        return beverage.getCost() + 4.0;
    }
}

// 使用示例
public class DecoratorPatternExample {
    public static void main(String[] args) {
        // 订一杯意式浓缩咖啡
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " ¥" + beverage.getCost());
        
        // 加牛奶
        beverage = new Milk(beverage);
        System.out.println(beverage.getDescription() + " ¥" + beverage.getCost());
        
        // 加摩卡
        beverage = new Mocha(beverage);
        System.out.println(beverage.getDescription() + " ¥" + beverage.getCost());
        
        // 加奶泡
        beverage = new WhippedCream(beverage);
        System.out.println(beverage.getDescription() + " ¥" + beverage.getCost());
        
        // 输出:
        // 意式浓缩咖啡 ¥25.0
        // 意式浓缩咖啡 + 牛奶 ¥28.0
        // 意式浓缩咖啡 + 牛奶 + 摩卡 ¥33.0
        // 意式浓缩咖啡 + 牛奶 + 摩卡 + 奶泡 ¥37.0
    }
}

六、建造者模式(Builder Pattern)

建造者模式使用多个简单的对象一步一步构建成一个复杂的对象。

实际应用:SQL查询构建器

public class SQLQueryBuilder {
    private StringBuilder query;
    private boolean hasWhere = false;
    
    public SQLQueryBuilder() {
        this.query = new StringBuilder();
    }
    
    public SQLQueryBuilder select(String... columns) {
        query.append("SELECT ");
        if (columns.length == 0) {
            query.append("*");
        } else {
            query.append(String.join(", ", columns));
        }
        return this;
    }
    
    public SQLQueryBuilder from(String table) {
        query.append(" FROM ").append(table);
        return this;
    }
    
    public SQLQueryBuilder where(String condition) {
        if (!hasWhere) {
            query.append(" WHERE ");
            hasWhere = true;
        } else {
            query.append(" AND ");
        }
        query.append(condition);
        return this;
    }
    
    public SQLQueryBuilder orderBy(String column, boolean ascending) {
        query.append(" ORDER BY ").append(column);
        if (!ascending) {
            query.append(" DESC");
        }
        return this;
    }
    
    public SQLQueryBuilder limit(int count) {
        query.append(" LIMIT ").append(count);
        return this;
    }
    
    public String build() {
        return query.toString();
    }
    
    // 使用示例
    public static void main(String[] args) {
        String sql = new SQLQueryBuilder()
                .select("name", "age", "email")
                .from("users")
                .where("age > 18")
                .where("status = 'active'")
                .orderBy("name", true)
                .limit(10)
                .build();
        
        System.out.println(sql);
        // 输出: SELECT name, age, email FROM users WHERE age > 18 AND status = 'active' ORDER BY name LIMIT 10
    }
}

复杂对象构建:用户信息建造者

public class User {
    private final String username;
    private final String email;
    private final String phone;
    private final String address;
    private final int age;
    private final boolean isVip;
    
    private User(Builder builder) {
        this.username = builder.username;
        this.email = builder.email;
        this.phone = builder.phone;
        this.address = builder.address;
        this.age = builder.age;
        this.isVip = builder.isVip;
    }
    
    public static class Builder {
        private String username;
        private String email;
        private String phone;
        private String address;
        private int age;
        private boolean isVip = false;
        
        public Builder(String username, String email) {
            this.username = username;
            this.email = email;
        }
        
        public Builder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public Builder address(String address) {
            this.address = address;
            return this;
        }
        
        public Builder age(int age) {
            if (age < 0) {
                throw new IllegalArgumentException("年龄不能为负数");
            }
            this.age = age;
            return this;
        }
        
        public Builder vip(boolean isVip) {
            this.isVip = isVip;
            return this;
        }
        
        public User build() {
            // 可以在这里添加验证逻辑
            if (username == null || username.trim().isEmpty()) {
                throw new IllegalStateException("用户名不能为空");
            }
            if (email == null || !email.contains("@")) {
                throw new IllegalStateException("邮箱格式不正确");
            }
            return new User(this);
        }
    }
    
    // toString方法
    @Override
    public String toString() {
        return String.format("User{username='%s', email='%s', phone='%s', address='%s', age=%d, isVip=%s}",
                username, email, phone, address, age, isVip);
    }
    
    // 使用示例
    public static void main(String[] args) {
        User user = new User.Builder("张三", "zhangsan@example.com")
                .phone("13800138000")
                .address("北京市朝阳区")
                .age(25)
                .vip(true)
                .build();
        
        System.out.println(user);
    }
}

设计模式的实际应用建议

1. 选择合适的模式

  • 单例模式:配置管理、日志记录、数据库连接池
  • 工厂模式:对象创建复杂、需要根据条件创建不同对象
  • 观察者模式:事件处理、MVC架构、消息通知
  • 策略模式:算法选择、支付方式、折扣计算
  • 装饰器模式:功能扩展、中间件、包装器
  • 建造者模式:复杂对象构建、配置对象创建

2. 避免过度设计

设计模式不是银弹,不要为了使用模式而使用模式。应该根据实际需求选择合适的模式。

3. 结合Spring框架

Spring框架大量使用了设计模式:

  • 依赖注入:工厂模式 + 装饰器模式
  • AOP:代理模式 + 装饰器模式
  • 事件机制:观察者模式
  • Bean作用域:单例模式 + 原型模式

4. 测试友好的设计

使用设计模式时要考虑可测试性,通过依赖注入和接口抽象使代码更容易测试。

总结

设计模式是程序员的重要工具,它们能帮助我们:

  1. 提高代码质量:使代码更加清晰、可维护
  2. 增强可扩展性:便于后续功能扩展
  3. 促进团队协作:提供统一的设计语言
  4. 避免重复造轮子:使用经过验证的解决方案

掌握设计模式需要大量实践,建议在实际项目中逐步应用这些模式,体会它们解决问题的思路和方法。记住,最好的代码不是使用了多少设计模式,而是能够清晰地表达业务逻辑,易于理解和维护。

通过合理运用设计模式,我们可以写出更优雅、更健壮的Java代码,提升自己的编程水平和软件设计能力。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注