Java设计模式实战指南:让你的代码更优雅
设计模式是软件开发中经过时间考验的解决方案,它们代表了最佳实践,能够帮助我们写出更加可维护、可扩展和可重用的代码。本文将深入探讨Java开发中最常用的设计模式,并通过实际案例展示它们的应用场景。
什么是设计模式?
设计模式是在特定环境下,为解决某一通用软件设计问题提供的一套定制的解决方案。它不是代码,而是解决问题的思路和方法。设计模式的核心思想是”找出程序中变化的部分,并将变化封装起来”。
设计模式的三大类型
- 创建型模式 – 关注对象的创建过程
- 结构型模式 – 关注类和对象的组合
- 行为型模式 – 关注对象间的通信和责任分配
一、单例模式(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. 测试友好的设计
使用设计模式时要考虑可测试性,通过依赖注入和接口抽象使代码更容易测试。
总结
设计模式是程序员的重要工具,它们能帮助我们:
- 提高代码质量:使代码更加清晰、可维护
- 增强可扩展性:便于后续功能扩展
- 促进团队协作:提供统一的设计语言
- 避免重复造轮子:使用经过验证的解决方案
掌握设计模式需要大量实践,建议在实际项目中逐步应用这些模式,体会它们解决问题的思路和方法。记住,最好的代码不是使用了多少设计模式,而是能够清晰地表达业务逻辑,易于理解和维护。
通过合理运用设计模式,我们可以写出更优雅、更健壮的Java代码,提升自己的编程水平和软件设计能力。
