行为型-策略模式

1. 项目结构

  1. 项目结构

    bash 复制代码
    	strategy-pattern-demo/
    	├── pom.xml
    	├── src/
    	│   ├── main/
    	│   │   ├── java/
    	│   │   │   └── com/
    	│   │   │       └── example/
    	│   │   │           └── strategy/
    	│   │   │               ├── PaymentStrategy.java
    	│   │   │               ├── CreditCardPayment.java
    	│   │   │               ├── PayPalPayment.java
    	│   │   │               ├── BitcoinPayment.java
    	│   │   │               ├── PaymentContext.java
    	│   │   │               ├── ShoppingCart.java
    	│   │   │               └── StrategyPatternDemo.java
    	│   │   └── resources/
    	│   └── test/
    	│       └── java/
    	│           └── com/
    	│               └── example/
    	│                   └── strategy/
    	│                       └── PaymentTest.java
  2. Maven 配置文件 (pom.xml)

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>strategy-pattern-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <junit.version>4.13.2</junit.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

2. 代码实现

  1. 策略接口 (PaymentStrategy.java)

    java 复制代码
    package com.example.strategy;
    
    /**
     * 支付策略接口
     * 定义所有支付方式的通用接口
     */
    @FunctionalInterface
    public interface PaymentStrategy {
        /**
         * 支付方法
         * @param amount 支付金额
         * @return 支付结果信息
         */
        String pay(double amount);
        
        /**
         * 默认方法:获取支付方式名称
         * JDK 1.8 引入的默认方法特性
         */
        default String getPaymentMethod() {
            return this.getClass().getSimpleName();
        }
    }
  2. 具体策略实现类-CreditCardPayment.java

    java 复制代码
    package com.example.strategy;
    
    /**
     * 信用卡支付策略
     */
    public class CreditCardPayment implements PaymentStrategy {
        private String cardNumber;
        private String cardHolder;
        private String cvv;
        
        public CreditCardPayment(String cardNumber, String cardHolder, String cvv) {
            this.cardNumber = cardNumber;
            this.cardHolder = cardHolder;
            this.cvv = cvv;
        }
        
        @Override
        public String pay(double amount) {
            // 模拟信用卡支付处理
            String maskedCardNumber = cardNumber.substring(0, 4) + "********" + cardNumber.substring(12);
            return String.format("成功使用信用卡支付 %.2f 元\n卡号: %s\n持卡人: %s", 
                    amount, maskedCardNumber, cardHolder);
        }
        
        @Override
        public String getPaymentMethod() {
            return "信用卡支付";
        }
    }
  3. 具体策略实现类-PayPalPayment.java

    java 复制代码
    package com.example.strategy;
    
    /**
     * PayPal支付策略
     */
    public class PayPalPayment implements PaymentStrategy {
        private String email;
        
        public PayPalPayment(String email) {
            this.email = email;
        }
        
        @Override
        public String pay(double amount) {
            // 模拟PayPal支付处理
            return String.format("成功使用PayPal支付 %.2f 元\nPayPal账户: %s", 
                    amount, email);
        }
        
        @Override
        public String getPaymentMethod() {
            return "PayPal支付";
        }
    }
  4. 具体策略实现类-BitcoinPayment.java

    java 复制代码
    package com.example.strategy;
    
    /**
     * 比特币支付策略
     */
    public class BitcoinPayment implements PaymentStrategy {
        private String walletAddress;
        
        public BitcoinPayment(String walletAddress) {
            this.walletAddress = walletAddress;
        }
        
        @Override
        public String pay(double amount) {
            // 模拟比特币支付处理
            String shortAddress = walletAddress.substring(0, 8) + "..." + walletAddress.substring(walletAddress.length() - 8);
            double btcAmount = amount / 50000.0; // 假设1 BTC = 50000 USD
            return String.format("成功使用比特币支付 %.2f 元 (约 %.6f BTC)\n钱包地址: %s", 
                    amount, btcAmount, shortAddress);
        }
        
        @Override
        public String getPaymentMethod() {
            return "比特币支付";
        }
    }
  5. 上下文类 (PaymentContext.java)

    java 复制代码
    package com.example.strategy;
    
    /**
     * 支付上下文
     * 维护对策略对象的引用,并允许客户端切换策略
     */
    public class PaymentContext {
        private PaymentStrategy paymentStrategy;
        private String orderId;
        
        public PaymentContext(String orderId) {
            this.orderId = orderId;
        }
        
        /**
         * 设置支付策略
         * @param paymentStrategy 支付策略
         */
        public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
            this.paymentStrategy = paymentStrategy;
        }
        
        /**
         * 执行支付
         * @param amount 支付金额
         * @return 支付结果
         */
        public String executePayment(double amount) {
            if (paymentStrategy == null) {
                throw new IllegalStateException("支付策略未设置");
            }
            
            System.out.println("=== 开始处理订单: " + orderId + " ===");
            System.out.println("支付方式: " + paymentStrategy.getPaymentMethod());
            System.out.println("支付金额: " + amount + " 元");
            
            String result = paymentStrategy.pay(amount);
            
            System.out.println("=== 订单处理完成 ===");
            return result;
        }
        
        /**
         * 使用Lambda表达式创建支付策略(JDK 1.8特性)
         * @param amount 支付金额
         * @param customPayment 自定义支付逻辑
         * @return 支付结果
         */
        public String executePayment(double amount, PaymentStrategy customPayment) {
            this.paymentStrategy = customPayment;
            return executePayment(amount);
        }
    }
  6. 购物车类 (ShoppingCart.java)

    java 复制代码
    package com.example.strategy;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 购物车类,用于演示策略模式的使用场景
     */
    public class ShoppingCart {
        private List<CartItem> items;
        private PaymentStrategy paymentStrategy;
        
        public ShoppingCart() {
            this.items = new ArrayList<>();
        }
        
        public void addItem(String name, double price, int quantity) {
            items.add(new CartItem(name, price, quantity));
        }
        
        public double calculateTotal() {
            return items.stream()
                       .mapToDouble(CartItem::getTotalPrice)
                       .sum();
        }
        
        public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
            this.paymentStrategy = paymentStrategy;
        }
        
        public String checkout() {
            double total = calculateTotal();
            
            if (paymentStrategy == null) {
                return "请先选择支付方式";
            }
            
            System.out.println("\n购物车内容:");
            items.forEach(item -> 
                System.out.println(String.format("- %s: %.2f × %d = %.2f 元", 
                    item.getName(), item.getPrice(), item.getQuantity(), item.getTotalPrice())));
            System.out.println(String.format("总计: %.2f 元", total));
            
            return paymentStrategy.pay(total);
        }
        
        // 内部类:购物车项
        private static class CartItem {
            private String name;
            private double price;
            private int quantity;
            
            public CartItem(String name, double price, int quantity) {
                this.name = name;
                this.price = price;
                this.quantity = quantity;
            }
            
            public String getName() { return name; }
            public double getPrice() { return price; }
            public int getQuantity() { return quantity; }
            public double getTotalPrice() { return price * quantity; }
        }
    }
  7. 主类 (StrategyPatternDemo.java)

    java 复制代码
    package com.example.strategy;
    
    /**
     * 策略模式演示类
     */
    public class StrategyPatternDemo {
        public static void main(String[] args) {
            System.out.println("======= 策略模式演示 =======\n");
            
            // 示例1: 使用PaymentContext管理支付策略
            System.out.println("示例1: 使用PaymentContext");
            PaymentContext context = new PaymentContext("ORD-2023-001");
            
            // 使用信用卡支付
            context.setPaymentStrategy(new CreditCardPayment("1234567812345678", "张三", "123"));
            System.out.println(context.executePayment(199.99));
            
            System.out.println("\n" + "=".repeat(50) + "\n");
            
            // 切换为PayPal支付
            context.setPaymentStrategy(new PayPalPayment("zhangsan@example.com"));
            System.out.println(context.executePayment(299.50));
            
            System.out.println("\n" + "=".repeat(50) + "\n");
            
            // 切换为比特币支付
            context.setPaymentStrategy(new BitcoinPayment("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"));
            System.out.println(context.executePayment(500.00));
            
            System.out.println("\n" + "=".repeat(50) + "\n");
            
            // 示例2: 使用Lambda表达式(JDK 1.8特性)
            System.out.println("示例2: 使用Lambda表达式");
            
            // 使用Lambda表达式创建自定义支付策略
            String result = context.executePayment(150.75, amount -> {
                return String.format("使用现金支付 %.2f 元\n请到前台完成支付", amount);
            });
            System.out.println(result);
            
            System.out.println("\n" + "=".repeat(50) + "\n");
            
            // 示例3: 购物车示例
            System.out.println("示例3: 购物车支付场景");
            ShoppingCart cart = new ShoppingCart();
            cart.addItem("Java编程思想", 89.90, 1);
            cart.addItem("设计模式", 59.90, 2);
            cart.addItem("数据结构与算法", 79.90, 1);
            
            // 设置支付策略
            cart.setPaymentStrategy(new CreditCardPayment("8765432187654321", "李四", "456"));
            
            // 结账
            System.out.println(cart.checkout());
            
            System.out.println("\n" + "=".repeat(50) + "\n");
            
            // 示例4: 方法引用(JDK 1.8特性)
            System.out.println("示例4: 使用方法引用");
            
            // 使用方法引用创建支付策略
            PaymentStrategy couponPayment = StrategyPatternDemo::couponPayment;
            context.setPaymentStrategy(couponPayment);
            System.out.println(context.executePayment(200.00));
        }
        
        // 静态方法,用于方法引用示例
        public static String couponPayment(double amount) {
            double discountedAmount = amount * 0.8; // 8折优惠
            return String.format("使用优惠券支付\n原价: %.2f 元\n折后价: %.2f 元\n优惠金额: %.2f 元", 
                    amount, discountedAmount, amount - discountedAmount);
        }
    }
  8. 测试类 (PaymentTest.java)

    java 复制代码
    package com.example.strategy;
    
    import org.junit.Test;
    import static org.junit.Assert.*;
    
    /**
     * 策略模式测试类
     */
    public class PaymentTest {
        
        @Test
        public void testCreditCardPayment() {
            PaymentStrategy strategy = new CreditCardPayment("1234567812345678", "张三", "123");
            String result = strategy.pay(100.00);
            assertTrue(result.contains("信用卡支付"));
            assertTrue(result.contains("100.00"));
        }
        
        @Test
        public void testPayPalPayment() {
            PaymentStrategy strategy = new PayPalPayment("test@example.com");
            String result = strategy.pay(200.50);
            assertTrue(result.contains("PayPal支付"));
            assertTrue(result.contains("test@example.com"));
        }
        
        @Test
        public void testBitcoinPayment() {
            PaymentStrategy strategy = new BitcoinPayment("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            String result = strategy.pay(300.00);
            assertTrue(result.contains("比特币支付"));
            assertTrue(result.contains("300.00"));
        }
        
        @Test
        public void testPaymentContext() {
            PaymentContext context = new PaymentContext("TEST-001");
            context.setPaymentStrategy(new CreditCardPayment("1111222233334444", "李四", "789"));
            
            String result = context.executePayment(150.00);
            assertTrue(result.contains("信用卡支付"));
            assertTrue(result.contains("150.00"));
        }
        
        @Test
        public void testShoppingCart() {
            ShoppingCart cart = new ShoppingCart();
            cart.addItem("商品A", 100.0, 2);
            cart.addItem("商品B", 50.0, 1);
            
            assertEquals(250.0, cart.calculateTotal(), 0.001);
            
            cart.setPaymentStrategy(amount -> "测试支付: " + amount);
            String result = cart.checkout();
            assertTrue(result.contains("250.00"));
        }
        
        @Test
        public void testLambdaPayment() {
            // 测试Lambda表达式实现的支付策略
            PaymentStrategy lambdaStrategy = amount -> 
                String.format("Lambda支付 %.2f 元", amount);
            
            String result = lambdaStrategy.pay(99.99);
            assertTrue(result.contains("Lambda支付"));
            assertTrue(result.contains("99.99"));
        }
    }

3. 构建和运行

  1. 编译项目

    bash 复制代码
    mvn clean compile
  2. 运行测试

    bash 复制代码
    mvn test
  3. 运行主程序

    bash 复制代码
    mvn compile exec:java -Dexec.mainClass="com.example.strategy.StrategyPatternDemo"

4. 核心概念

  • 策略接口 (PaymentStrategy):定义了所有支付策略的通用接口
  • 具体策略 (CreditCardPayment, PayPalPayment, BitcoinPayment):实现了策略接口的具体算法
  • 上下文类 (PaymentContext):维护对策略对象的引用,并可以切换策略
  • 客户端代码 (StrategyPatternDemo):创建具体策略对象并传递给上下文
相关推荐
崎岖Qiu6 天前
【设计模式笔记24】:JDK源码分析-Comparator中的「策略模式」
java·笔记·设计模式·jdk·策略模式
辣机小司8 天前
【踩坑记录:EasyExcel 生产级实战:策略模式重构与防御性导入导出校验指南(实用工具类分享)】
java·spring boot·后端·重构·excel·策略模式·easyexcel
山风wind9 天前
设计模式-策略模式详解
设计模式·策略模式
“抚琴”的人10 天前
C#上位机策略模式
开发语言·c#·策略模式
梦里小白龙10 天前
JAVA 策略模式+工厂模式
java·开发语言·策略模式
秋邱11 天前
Java面向对象进阶实战:用工厂模式+策略模式优化支付系统
java·bash·策略模式
吃喝不愁霸王餐APP开发者13 天前
基于策略模式动态选择不同地区霸王餐API接口的路由实现
策略模式
未来之窗软件服务13 天前
幽冥大陆(六十三) roff 语言:核心用途与使用指南—东方仙盟筑基期
策略模式·东方仙盟·roff