JAVA设计模式(持续更新)

策略模式

策略模式(Strategy Pattern)是一种行为设计模式,它定义一系列算法,将每个算法封装起来,并使它们可以互相替换,使得算法可以独立于使用它的客户端变化。以下是实际开发中的典型使用场景、示例及最佳实践:

核心概念

意图:分离算法的定义与使用,避免多重条件判断。
核心角色
策略接口(Strategy):定义算法的公共接口(如 PaymentStrategy)。
具体策略(Concrete Strategy):实现策略接口的具体算法(如 CreditCardPayment、AlipayPayment)。
上下文(Context):持有策略引用,负责调用策略(如 Order 类)。

实际使用场景

场景 1:支付方式选择
需求:电商平台支持多种支付方式(信用卡、支付宝、微信支付),需动态切换支付逻辑。

// 1. 定义策略接口
interface PaymentStrategy {
void pay(double amount);
}

// 2. 实现具体策略

class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via Credit Card");
    }
}

class AlipayPayment implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via Alipay");
    }
}

// 3. 上下文类(持有策略)
class Order {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }

    public void checkout(double amount) {
        paymentStrategy.pay(amount);
    }
}

// 4. 客户端调用
public class Main {
    public static void main(String[] args) {
        Order order = new Order();
        
        // 动态切换策略
        order.setPaymentStrategy(new CreditCardPayment());
        order.checkout(100.0);  // 输出: Paid 100.0 via Credit Card

        order.setPaymentStrategy(new AlipayPayment());
        order.checkout(200.0);  // 输出: Paid 200.0 via Alipay
    }
}

优势:新增支付方式(如微信支付)只需添加新策略类,无需修改 Order 类。

场景 2:排序算法切换
需求:根据数据规模动态选择排序算法(快速排序、归并排序)。

// 策略接口
interface SortStrategy {
    void sort(int[] array);
}

// 具体策略
class QuickSort implements SortStrategy {
    @Override
    public void sort(int[] array) {
        System.out.println("Sorting using QuickSort");
        // 实际实现省略
    }
}

class MergeSort implements SortStrategy {
    @Override
    public void sort(int[] array) {
        System.out.println("Sorting using MergeSort");
        // 实际实现省略
    }
}

// 上下文
class Sorter {
    private SortStrategy strategy;

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void executeSort(int[] array) {
        strategy.sort(array);
    }
}

// 使用示例
Sorter sorter = new Sorter();
int[] data = {5, 2, 9, 1};

sorter.setStrategy(new QuickSort());
sorter.executeSort(data);  // 输出: Sorting using QuickSort

sorter.setStrategy(new MergeSort());
sorter.executeSort(data);  // 输出: Sorting using MergeSort

场景 3:折扣策略(电商促销)
需求:根据活动类型(无折扣、满减、会员折扣)动态计算价格。

interface DiscountStrategy {
    double applyDiscount(double originalPrice);
}

class NoDiscount implements DiscountStrategy {
    @Override
    public double applyDiscount(double price) {
        return price;
    }
}

class FullReductionDiscount implements DiscountStrategy {
    @Override
    public double applyDiscount(double price) {
        return price >= 100 ? price - 20 : price;
    }
}

class ShoppingCart {
    private DiscountStrategy discountStrategy;

    public void setDiscountStrategy(DiscountStrategy strategy) {
        this.discountStrategy = strategy;
    }

    public double checkout(double price) {
        return discountStrategy.applyDiscount(price);
    }
}

// 使用示例
ShoppingCart cart = new ShoppingCart();
cart.setDiscountStrategy(new FullReductionDiscount());
double finalPrice = cart.checkout(150.0);  // 输出 130.0

策略模式的变体与优化

(1)使用 Lambda 简化(Java 8+)
若策略接口只有一个方法,可直接用 Lambda 或方法引用替代具体策略类。

// 支付策略示例的简化版
Order order = new Order();
order.setPaymentStrategy(amount -> System.out.println("Paid " + amount + " via WeChat Pay"));
order.checkout(50.0);

(2)策略枚举
适用于策略类型固定的场景。

enum DiscountType implements DiscountStrategy {
    NO_DISCOUNT {
        public double applyDiscount(double price) { return price; }
    },
    MEMBER_DISCOUNT {
        public double applyDiscount(double price) { return price * 0.9; }
    };
}

// 使用
double price = DiscountType.MEMBER_DISCOUNT.applyDiscount(200.0);

(3)策略工厂
集中管理策略的创建逻辑。

class PaymentStrategyFactory {
    static PaymentStrategy getStrategy(String type) {
        switch (type) {
            case "alipay": return new AlipayPayment();
            case "credit": return new CreditCardPayment();
            default: throw new IllegalArgumentException("Unsupported payment type");
        }
    }
}

// 客户端调用
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy("alipay");

代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。

代理模式的核心概念

代理模式包含三个主要角色:
抽象主题(Subject): 定义真实主题和代理主题的共同接口
真实主题(Real Subject): 实现真正的业务逻辑
代理(Proxy): 控制对真实主题的访问,可以在调用真实主题前后添加额外操作

静态代理

静态代理是在编译时就确定代理关系的实现方式。

示例代码

// 1. 定义抽象主题
interface Image {
    void display();
}

// 2. 定义真实主题
class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading " + fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }
}

// 3. 定义代理
class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;

    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}

// 4. 使用代理
public class StaticProxyDemo {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");
        // 第一次调用会创建真实对象
        image.display();
        // 第二次调用直接使用已创建的真实对象
        image.display();
    }
}

静态代理特点
优点:简单直观
缺点:每个真实主题都需要一个代理类,代码量大

动态代理

动态代理是在程序运行时,通过反射机制动态生成的代理类。Java提供了java.lang.reflect.Proxy类来实现动态代理。Java提供了两种主要方式:
JDK动态代理(基于接口)
CGLIB动态代理(基于类)

JDK动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 1. 定义抽象主题
interface UserService {
    void addUser(String name);
    void deleteUser(String name);
}

// 2. 定义真实主题
class UserServiceImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }

    @Override
    public void deleteUser(String name) {
        System.out.println("删除用户: " + name);
    }
}

// 3. 定义调用处理器
class UserServiceInvocationHandler implements InvocationHandler {
    private Object target;

    public UserServiceInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("--- 前置处理 ---");
        Object result = method.invoke(target, args);
        System.out.println("--- 后置处理 ---");
        return result;
    }
}

// 4. 使用动态代理
public class JdkProxyDemo {
    public static void main(String[] args) {
        UserService realService = new UserServiceImpl();
        
        UserService proxy = (UserService) Proxy.newProxyInstance(
            realService.getClass().getClassLoader(),
            realService.getClass().getInterfaces(),
            new UserServiceInvocationHandler(realService)
        );
        
        proxy.addUser("张三");
        proxy.deleteUser("李四");
    }
}

CGLIB动态代理

需要添加CGLIB依赖:
示例代码:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

// 1. 定义真实主题(不需要接口)
class ProductService {
    public void addProduct(String name) {
        System.out.println("添加产品: " + name);
    }
    
    public void deleteProduct(String name) {
        System.out.println("删除产品: " + name);
    }
}

// 2. 定义方法拦截器
class ProductMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("--- 前置处理 ---");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("--- 后置处理 ---");
        return result;
    }
}

// 3. 使用CGLIB代理
public class CglibProxyDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ProductService.class);
        enhancer.setCallback(new ProductMethodInterceptor());
        
        ProductService proxy = (ProductService) enhancer.create();
        
        proxy.addProduct("手机");
        proxy.deleteProduct("电脑");
    }
}

代理模式的应用场景

远程代理:为一个对象在不同地址空间提供局部代表,以便隐藏实际对象存在于不同地址空间的事实。
虚拟代理:根据需要创建开销大的对象,通过代理对象来控制对真实对象的访问。
安全代理:控制真实对象的访问权限,确保用户只能进行允许的操作。
智能引用代理:在访问对象时执行一些附加操作,如记录访问日志、统计访问次数等。
AOP实现:Spring AOP就是基于动态代理实现的

代理模式的优缺点

优点:
职责清晰,真实主题只需关注核心业务
高扩展性,可以在不修改真实主题的情况下增加功能
作为调用方和真实主题之间的中介,保护真实主题

缺点:
增加了系统复杂度
在客户端和真实主题之间增加了代理对象,可能会影响性能

JDK动态代理与CGLIB动态代理比较

特性 JDK动态代理 CGLIB动态代理
基于 接口
性能 较慢(反射调用) 较快(方法索引直接调用)
生成方式 反射 字节码生成
方法final限制 无法代理final方法

Spring AOP 的代理实现方式

Spring AOP 主要使用两种代理模式:
JDK 动态代理(基于接口)

  • 当目标对象实现了至少一个接口时使用
  • 基于 java.lang.reflect.Proxy 类创建代理
  • 只能代理接口中定义的方法

CGLIB 代理(基于类)

  • 当目标对象没有实现任何接口时使用
  • 通过生成目标类的子类来实现代理
  • 可以代理类中的方法(final方法除外)

工厂模式

单例模式

你可能感兴趣的:(java,设计模式,开发语言)