深入学习Java中的常用设计模式:单例模式、工厂模式、观察者模式、策略模式等经典设计模式的原理、实现和应用场景
设计模式是在软件设计中常见问题的典型解决方案。它们就像预先制作的蓝图,可以定制来解决代码中反复出现的设计问题。设计模式不是具体的代码,而是解决特定问题的通用概念。
处理对象创建机制,试图根据实际情况使用合适的方式创建对象。
处理对象和类的组合,通过继承和组合来组成更大的结构。
关注对象之间的通信和职责分配,处理算法和对象间的责任分配。
单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于需要控制资源访问的场景,如数据库连接池、日志记录器、配置管理器等。
饿汉式单例在类加载时就创建实例,线程安全但可能造成内存浪费。
/**
* 饿汉式单例模式
*
* 特点:
* - 类加载时就创建实例
* - 线程安全
* - 可能造成内存浪费
*/
public class EagerSingleton {
// 在类加载时就创建实例
private static final EagerSingleton INSTANCE = new EagerSingleton();
/**
* 私有构造函数,防止外部实例化
*/
private EagerSingleton() {
System.out.println("EagerSingleton实例被创建");
}
/**
* 获取单例实例
*
* @return 单例实例
*/
public static EagerSingleton getInstance() {
return INSTANCE;
}
/**
* 业务方法示例
*/
public void doSomething() {
System.out.println("EagerSingleton正在执行业务逻辑...");
}
}
懒汉式单例延迟创建实例,需要时才创建,但需要考虑线程安全问题。
/**
* 懒汉式单例模式(线程安全版本)
*
* 特点:
* - 延迟加载,需要时才创建实例
* - 使用synchronized保证线程安全
* - 性能相对较低
*/
public class LazySingleton {
// 静态实例变量
private static LazySingleton instance;
/**
* 私有构造函数
*/
private LazySingleton() {
System.out.println("LazySingleton实例被创建");
}
/**
* 获取单例实例(线程安全)
*
* @return 单例实例
*/
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
/**
* 业务方法示例
*/
public void doSomething() {
System.out.println("LazySingleton正在执行业务逻辑...");
}
}
双重检查锁定(Double-Checked Locking)是懒汉式的优化版本,减少了同步开销。
/**
* 双重检查锁定单例模式
*
* 特点:
* - 延迟加载
* - 线程安全
* - 性能较好
*/
public class DoubleCheckedSingleton {
// 使用volatile确保多线程环境下的可见性
private static volatile DoubleCheckedSingleton instance;
/**
* 私有构造函数
*/
private DoubleCheckedSingleton() {
System.out.println("DoubleCheckedSingleton实例被创建");
}
/**
* 获取单例实例(双重检查锁定)
*
* @return 单例实例
*/
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
/**
* 业务方法示例
*/
public void doSomething() {
System.out.println("DoubleCheckedSingleton正在执行业务逻辑...");
}
}
工厂模式提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
/**
* 形状接口
*/
public interface Shape {
/**
* 绘制形状
*/
void draw();
}
/**
* 圆形类
*/
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
/**
* 形状工厂类
*/
public class ShapeFactory {
/**
* 根据形状类型创建对应的形状对象
*
* @param shapeType 形状类型
* @return 形状对象
*/
public static Shape createShape(String shapeType) {
if (shapeType == null || shapeType.isEmpty()) {
return null;
}
switch (shapeType.toUpperCase()) {
case "CIRCLE":
return new Circle();
case "RECTANGLE":
return new Rectangle();
case "TRIANGLE":
return new Triangle();
default:
throw new IllegalArgumentException("未知的形状类型: " + shapeType);
}
}
}
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
/**
* 观察者接口
*/
public interface Observer {
/**
* 更新方法,当被观察者状态改变时调用
*
* @param news 新闻内容
*/
void update(String news);
}
/**
* 被观察者接口(主题)
*/
public interface Subject {
/**
* 添加观察者
*
* @param observer 观察者
*/
void addObserver(Observer observer);
/**
* 移除观察者
*
* @param observer 观察者
*/
void removeObserver(Observer observer);
/**
* 通知所有观察者
*
* @param news 新闻内容
*/
void notifyObservers(String news);
}
import java.util.ArrayList;
import java.util.List;
/**
* 新闻机构类(具体的被观察者)
*/
public class NewsAgency implements Subject {
private List observers = new ArrayList<>();
private String latestNews;
@Override
public void addObserver(Observer observer) {
observers.add(observer);
System.out.println("添加了一个新的观察者");
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
System.out.println("移除了一个观察者");
}
@Override
public void notifyObservers(String news) {
System.out.println("通知所有观察者: " + news);
for (Observer observer : observers) {
observer.update(news);
}
}
/**
* 发布新闻
*
* @param news 新闻内容
*/
public void publishNews(String news) {
this.latestNews = news;
notifyObservers(news);
}
}
策略模式定义了一系列算法,把它们一个个封装起来,并且使它们可相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。
/**
* 支付策略接口
*/
public interface PaymentStrategy {
/**
* 执行支付
*
* @param amount 支付金额
*/
void pay(double amount);
}
/**
* 信用卡支付策略
*/
public class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String cardHolder;
public CreditCardPayment(String cardNumber, String cardHolder) {
this.cardNumber = cardNumber;
this.cardHolder = cardHolder;
}
@Override
public void pay(double amount) {
System.out.println(String.format("使用信用卡支付 %.2f 元", amount));
System.out.println("卡号: " + maskCardNumber(cardNumber));
System.out.println("持卡人: " + cardHolder);
}
private String maskCardNumber(String cardNumber) {
return cardNumber.substring(0, 4) + " **** **** " +
cardNumber.substring(cardNumber.length() - 4);
}
}
/**
* 支付上下文类
*/
public class PaymentContext {
private PaymentStrategy paymentStrategy;
/**
* 设置支付策略
*
* @param paymentStrategy 支付策略
*/
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
/**
* 执行支付
*
* @param amount 支付金额
*/
public void executePayment(double amount) {
if (paymentStrategy == null) {
throw new IllegalStateException("支付策略未设置");
}
paymentStrategy.pay(amount);
}
}