java设计模式实战【策略模式+观察者模式+命令模式+组合模式,混合模式在支付系统中的应用】

引言

在代码开发的世界里,理论知识的重要性毋庸置疑,但实战经验往往才是知识的真正试金石。正所谓,"读万卷书不如行万里路",理论的学习需要通过实践来验证和深化。设计模式作为软件开发中的重要理论,其真正的价值在于它们在解决实际问题时的应用。之前的一篇文章中,我们通过物流系统,引入了策略+工厂方法模式,感兴趣的读者可以去阅读Java设计模式实战:从If-Else到策略+工厂方法的演变,本文将再通过支付系统来展示策略模式+观察者模式+命令模式+组合模式的混合模式在实际开发中的应用。

本文不仅是对设计模式的理论讲解,更是一次深入实战的探索。无论你是一名经验丰富的开发者还是刚入行的新手,看一遍肯定记不住,请记得收藏本文,相信一定会为你在未来工作中,引入设计模式提供一份参考

目录

  1. 案例分析
    • 支付系统概述
    • 关键功能
    • 面临的挑战
  2. 初始代码
    • 定义Payment实体类
    • 定义PaymentSystemService接口
    • 定义PaymentSystemServiceImpl实现类
    • 模拟调用
  3. 初始代码存在的问题分析
  4. 引入策略模式
    • 策略模式介绍
    • 引入策略模式后的代码
    • 引入策略模式后存在的问题分析
  5. 引入观察者模式
    • 观察者模式介绍
    • 引入观察者模式后的代码
    • 引入观察者模式后存在的问题分析
  6. 引入命令+组合模式
    • 命令及组合模式介绍
    • 引入命令+组合模式后的代码
    • 引入命令+组合模式后的分析
  7. 混合模式设计的系统优势
  8. 写在最后

案例分析

支付系统概述

简单来说支付系统需要处理多种支付方式,还要与其他系统组件,比如风控、营销等系统进行交互,是比较复杂且难以设计的一类系统。我们就以支付系统为例,引入混合设计模式来优化

关键功能
  1. 多渠道支付处理:支持多种支付渠道,如信用卡、电子钱包、银行转账等。用户可以根据自己的偏好选择合适的支付方式
  2. 支付状态跟踪:需要跟踪和管理每笔交易的状态,确保交易的顺利完成
  3. 风控通知:在支付过程中,系统需要与风控等系统交互,确保交易的安全性
  4. 日志记录:系统应记录所有关键的支付信息,用于审计和故障排查
  5. 组合支付支持:系统应支持组合支付,即允许用户在一次交易中使用多种支付方式
面临的挑战
  1. 高耦合度:不同支付渠道的处理逻辑紧密耦合,使得系统难以适应新支付方式的添加或现有方式的修改
  2. 通知机制不灵活:支付完成后的通知机制(如风控通知和日志记录)固定且不易扩展,难以适应多变的业务需求
  3. 组合支付复杂性:支持组合支付(比如 余额+银行卡),增加了系统的复杂性,尤其是在处理多种支付方式的交互和状态管理时
  4. 维护和扩展困难:由于系统的复杂性和高耦合度,新功能的添加和现有功能的维护变得困难和风险较高

在接下来的部分中,我们将探讨如何通过引入策略模式、观察者模式和命令及组合模式的混合模式来解决这些挑战,提高支付系统的灵活性、可扩展性和可维护性

初始代码

①定义Payment实体类:

java 复制代码
import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;

class Payment {
    String paymentType;
    BigDecimal amount;

    Payment(String paymentType, BigDecimal amount) {
        this.paymentType = paymentType;
        this.amount = amount;
    }
}

②定义PaymentSystemService接口:

java 复制代码
import java.util.List;

public interface PaymentSystemService {
    void processPayments(List<Payment> payments);
}

③定义PaymentSystemServiceImpl实现类:

java 复制代码
public class PaymentSystemServiceImpl implements PaymentSystemService {

    @Override
    public void processPayments(List<Payment> payments) {
    	// 处理支付
        processPaymentMethod(payments);
        // 支付完成后的通知
        notifyRiskManagement(payments);
		// 上报埋点日志
        logTransactions(payments);
    }

    private void processPaymentMethod(List<Payment> payments) {
        for (Payment payment : payments) {
            switch (payment.paymentType) {
                case "CreditCard":
                    System.out.println("Processing credit card payment: " + payment.amount);
                    break;
                case "PayPal":
                    System.out.println("Processing PayPal payment: " + payment.amount);
                    break;
                // 其他支付方式...
            }
        }
    }
	
	// 通知风控
    private void notifyRiskManagement(List<Payment> payments) {
        System.out.println("Notifying risk management for payment.");
    }
	
	// 日志埋点
    private void logTransactions(List<Payment> payments) {
        for (Payment payment : payments) {
            System.out.println("Logging transaction: Payment type: " + 
            payment.paymentType + ", Amount: " + payment.amount);
        }
    }
}

④模拟调用

java 复制代码
public class Main {
    public static void main(String[] args) {
        PaymentSystemService paymentService = new PaymentSystemServiceImpl();

        // 示例:组合支付
        List<Payment> combinedPayments = new ArrayList<>();
        combinedPayments.add(new Payment("CreditCard", new BigDecimal("50.0")));
        combinedPayments.add(new Payment("PayPal", new BigDecimal("25.0")));
        paymentService.processPayments(combinedPayments);

        // 示例:单一支付
        // List<Payment> singlePayment = new ArrayList<>();
        // singlePayment.add(new Payment("CreditCard", new BigDecimal("75.0")));
        // paymentService.processPayments(singlePayment);
    }
}

初始代码存在的问题分析

在上述的初始实现中,PaymentSystemServiceImpl 类直接处理了所有的支付逻辑。这种实现方式存在几个主要问题:

  1. 高耦合度:支付逻辑直接与 PaymentSystemServiceImpl 类耦合,使得该类承担了过多的责任。每种支付方式的逻辑都集中在一个类中,违反了单一职责原则
  2. 扩展性差:添加或修改支付方式都需要修改 PaymentSystemServiceImpl 类,这违反了开闭原则
  3. 通知机制僵化:支付完成后的通知机制(如风控通知和日志记录)与支付逻辑紧密耦合,缺乏灵活性。难以适应不断变化的业务需求,必如需要增加新的通知类型或修改通知流程

为了解决这些问题,我们第一时间可以考虑引入策略模式来处理不同支付方式的逻辑,使得每种支付方式都有自己的策略类,解决这个主要问题

引入策略模式

策略模式介绍

策略模式是一种行为设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以互换。策略模式让算法的变化独立于使用算法的客户

在支付系统中,我们可以定义一个支付策略接口,每种支付方式实现这个接口。PaymentSystemServiceImpl 类可以使用这些策略来处理不同的支付方式,而不是直接实现所有支付逻辑

引入策略模式后的代码

①定义策略接口PaymentStrategy以及具体的策略类CreditCardPaymentStrategy...:

java 复制代码
import java.math.BigDecimal;

/**
 * 定义支付策略的接口。
 */
public interface PaymentStrategy {

    /**
     * 检查此策略是否适用于指定的支付类型。
     *
     * @param paymentType 支付类型
     * @return 如果策略适用于该支付类型,则返回 true
     */
    boolean appliesTo(String paymentType);

    /**
     * 处理支付。
     *
     * @param amount 支付金额
     */
    void processPayment(BigDecimal amount);
}

/**
 * 信用卡支付策略。
 */
public class CreditCardPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean appliesTo(String paymentType) {
        return "CreditCard".equals(paymentType);
    }

    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing credit card payment: " + amount);
        // 实现信用卡支付逻辑
    }
}

/**
 * PayPal支付策略。
 */
public class PayPalPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean appliesTo(String paymentType) {
        return "PayPal".equals(paymentType);
    }

    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing PayPal payment: " + amount);
        // 实现PayPal支付逻辑
    }
}

②修改PaymentSystemServiceImpl类:

java 复制代码
public class PaymentSystemServiceImpl implements PaymentSystemService {

    private List<PaymentStrategy> paymentStrategies;

    public setPaymentStrategy(List<PaymentStrategy> paymentStrategies) {
        this.paymentStrategies = paymentStrategies;
    }

    @Override
    public void processPayments(List<Payment> payments) {
        for (Payment payment : payments) {
        	// 匹配策略
            PaymentStrategy strategy = paymentStrategies.stream()
                .filter(s -> s.appliesTo(payment.paymentType))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("
                	No strategy found for payment type: " + payment.paymentType));
            strategy.processPayment(payment.amount);
        }

        // 支付完成后的通知
        notifyRiskManagement(payments);
        logTransactions(payments);
    }

    // ... notifyRiskManagement and logTransactions methods ...
}

③模拟调用

java 复制代码
public class Main {
    public static void main(String[] args) {
    	// 构造策略
        List<PaymentStrategy> strategies = new ArrayList<>();
        strategies.add(new CreditCardPaymentStrategy());
        strategies.add(new PayPalPaymentStrategy());
		
		// 注入策略
        PaymentSystemService paymentService = new PaymentSystemServiceImpl();
        paymentService.setPaymentStrategy(stategies);
		
		// 模拟组合支付场景
        List<Payment> payments = new ArrayList<>();
        payments.add(new Payment("CreditCard", new BigDecimal("50.0")));
        payments.add(new Payment("PayPal", new BigDecimal("25.0")));

        paymentService.processPayments(payments);
    }
}

引入策略模式后存在的问题分析

先看下当前代码的类图结构:

这个类图包括以下部分:

  • PaymentSystemService 接口,定义了处理支付的方法
  • PaymentSystemServiceImpl 类,实现了 PaymentSystemService 接口,并使用策略模式处理支付
  • PaymentStrategy 接口,定义了支付策略的方法
  • CreditCardPaymentStrategyPayPalPaymentStrategy 类,实现了 PaymentStrategy 接口,分别表示信用卡和PayPal的支付策略

存在的问题点:

  • 通知机制僵化:该问题依然存在,如果后续需要新增,比如财务记账通知,需要修改PaymentSystemService,显然违背了单一职责
  • 策略管理复杂性:尽管观察者模式优化了通知机制,但支付策略的管理(如策略的选择和执行)仍然是 PaymentSystemServiceImpl 类的责任,这可能导致策略管理复杂
  • 组合支付处理不足:当前的实现可能不足以优雅地处理组合支付场景,即在单次交易中使用多种支付方式。这需要更复杂的逻辑来协调不同支付方式的处理

因此我们考虑一个个问题依次解决,先引入观察者模式,以便解耦PaymentSystemServiceImpl类与通知,通知交给具体的观察者即可。这样可以用于实现更灵活的通知机制,后续可以动态添加或修改观察者

引入观察者模式

观察者模式介绍

观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合实现事件处理系统。

在观察者模式中,存在两类主要角色:

  1. 主题(Subject):维护一系列观察者,提供用于注册和注销观察者的接口
  2. 观察者(Observer):提供一个更新接口,用于接收来自主题的通知

引入策略模式后的代码

java 复制代码
import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;

// 观察者接口
interface Observer {
    void update(Payment payment);
}

// 主题接口
interface Subject {
	// 注册观察者
    void registerObserver(Observer o);
    // 移除观察者
    void removeObserver(Observer o);
    // 通知观察者
    void notifyObservers(Payment payment);
}

// 支付策略接口
interface PaymentStrategy {
    boolean appliesTo(String paymentType);
    void processPayment(BigDecimal amount);
}

// 具体的支付策略实现
class CreditCardPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean appliesTo(String paymentType) {
        return "CreditCard".equals(paymentType);
    }

    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing credit card payment: " + amount);
    }
}

class PayPalPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean appliesTo(String paymentType) {
        return "PayPal".equals(paymentType);
    }

    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing PayPal payment: " + amount);
    }
}

// 支付服务实现类
class PaymentSystemServiceImpl implements PaymentSystemService, Subject {
    private List<Observer> observers = new ArrayList<>();
    private List<PaymentStrategy> paymentStrategies;

    public PaymentSystemServiceImpl(List<PaymentStrategy> paymentStrategies) {
        this.paymentStrategies = paymentStrategies;
    }

    @Override
    public void processPayments(List<Payment> payments) {
        for (Payment payment : payments) {
            PaymentStrategy strategy = paymentStrategies.stream()
                .filter(s -> s.appliesTo(payment.paymentType))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("No strategy 
                	found for payment type: " + payment.paymentType));
            strategy.processPayment(payment.amount);
            notifyObservers(payment);
        }
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyObservers(Payment payment) {
        for (Observer observer : observers) {
            observer.update(payment);
        }
    }
}

// 支付类
class Payment {
    String paymentType;
    BigDecimal amount;

    Payment(String paymentType, BigDecimal amount) {
        this.paymentType = paymentType;
        this.amount = amount;
    }
}

// 风控系统观察者
class RiskManagementObserver implements Observer {
    @Override
    public void update(Payment payment) {
        System.out.println("Risk Management notified for payment: " + payment.amount);
        // 实现风控逻辑
        notifyRiskManagement(payment);
    }

    private void notifyRiskManagement(Payment payment) {
        // 风控通知逻辑
    }
}

// 日志系统观察者
class LoggingObserver implements Observer {
    @Override
    public void update(Payment payment) {
        System.out.println("Logging payment transaction: " + payment.amount);
        // 实现日志记录逻辑
        logTransaction(payment);
    }

    private void logTransaction(Payment payment) {
        // 日志记录逻辑
    }
}

// 主方法
public class Main {
    public static void main(String[] args) {
        List<PaymentStrategy> strategies = new ArrayList<>();
        strategies.add(new CreditCardPaymentStrategy());
        strategies.add(new PayPalPaymentStrategy());

        PaymentSystemServiceImpl paymentService = new PaymentSystemServiceImpl(strategies);
        paymentService.registerObserver(new RiskManagementObserver());
        paymentService.registerObserver(new LoggingObserver());

        List<Payment> payments = new ArrayList<>();
        payments.add(new Payment("CreditCard", new BigDecimal("50.0")));
        payments.add(new Payment("PayPal", new BigDecimal("25.0")));

        paymentService.processPayments(payments);
    }
}

引入观察者模式后存在的问题分析

引入观察者模式后的类图:

组合支付的时序流程图:

引入观察者模式后解决的问题

  • 解耦通知机制

  • 观察者模式将支付完成后的通知逻辑(如风控通知和日志记录)从 PaymentSystemServiceImpl 类中解耦出来。每个观察者负责处理特定的响应逻辑,降低了主类的复杂性

  • 提高灵活性和可扩展性

  • 通过观察者模式,可以轻松添加或移除观察者,无需修改主类的代码。这使得在支付系统中引入新的通知类型(如财务记账通知)变得更加简单

  • 更好地遵循单一职责原则

  • 观察者模式使得每个类(包括主类和观察者)都专注于单一的职责,提高了代码的可维护性

引入观察者模式后仍存在的问题

  • 策略管理复杂性 :问题依然存在,尽管观察者模式优化了通知机制,但支付策略的管理(如策略的选择和执行)仍然是 PaymentSystemServiceImpl 类的责任,这可能导致策略管理复杂

  • 组合支付处理不足:问题依然存在,当前的实现可能不足以优雅地处理组合支付场景,即在单次交易中使用多种支付方式。这需要更复杂的逻辑来协调不同支付方式的处理

解决策略:

  • 对于第一个问题,之前有介绍过用工厂方法模式解决,感兴趣的读者可以去阅读Java设计模式实战:从If-Else到策略+工厂方法的演变,本篇文章我们换一种模式,用命令模式来解决(很多设计模式其实都可以相互替换)
  • 对于第二个问题,我们可以考虑引入组合模式。组合模式可以用于优雅地处理组合支付场景,允许将多个支付方式组合成一个支付请求。这样,我们可以将组合支付的逻辑从 PaymentSystemServiceImpl 类中分离出来,进一步提高系统的灵活性和可维护性

引入命令+组合模式

命令及组合模式介绍

  • 命令模式:适用于管理和封装支付策略的执行逻辑。可以将支付操作封装为命令对象,使得支付处理逻辑与执行逻辑分离,提高代码的可重用性和可维护性。有助于实现撤销(undo)和重做(redo)等操作,增加系统的灵活性
  • 组合模式:适用于处理组合支付场景,即在单次交易中使用多种支付方式。允许客户端以统一的方式处理单个支付组合支付,简化了客户端的使用。提高了代码的结构清晰度和可扩展性

引入命令+组合模式后的代码

java 复制代码
import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;

// 观察者接口
interface Observer {
    void update(BigDecimal amount);
}

// 主题接口
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers(BigDecimal amount);
}

// 命令接口
interface PaymentCommand {
    void execute();
}

// 具体的支付命令
class ConcretePaymentCommand implements PaymentCommand {
    private PaymentStrategy strategy;
    private BigDecimal amount;
    private Subject subject;

    ConcretePaymentCommand(PaymentStrategy strategy, BigDecimal amount, Subject subject) {
        this.strategy = strategy;
        this.amount = amount;
        this.subject = subject;
    }

    @Override
    public void execute() {
        strategy.processPayment(amount);
        subject.notifyObservers(amount);
    }
}

// 支付策略接口
interface PaymentStrategy {
    void processPayment(BigDecimal amount);
}

// 具体的支付策略
class CreditCardPaymentStrategy implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing credit card payment: " + amount);
    }
}

class PayPalPaymentStrategy implements PaymentStrategy {
    @Override
    public void processPayment(BigDecimal amount) {
        System.out.println("Processing PayPal payment: " + amount);
    }
}

// 支付组件接口(组合模式)
interface PaymentComponent {
    void processPayment();
}

// 单一支付(叶子节点)
class SinglePayment implements PaymentComponent {
    private PaymentCommand command;

    SinglePayment(PaymentCommand command) {
        this.command = command;
    }

    @Override
    public void processPayment() {
        command.execute();
    }
}

// 组合支付(复合节点)
class CompositePayment implements PaymentComponent {
    private List<PaymentComponent> payments = new ArrayList<>();

    void addPayment(PaymentComponent payment) {
        payments.add(payment);
    }

    @Override
    public void processPayment() {
        for (PaymentComponent payment : payments) {
            payment.processPayment();
        }
    }
}

// 支付服务实现(同时作为主题)
class PaymentSystemServiceImpl implements Subject {
    private List<Observer> observers = new ArrayList<>();

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyObservers(BigDecimal amount) {
        for (Observer observer : observers) {
            observer.update(amount);
        }
    }

    void processPayments(PaymentComponent paymentComponent) {
        paymentComponent.processPayment();
    }
}

// 观察者实现
class RiskManagementObserver implements Observer {
    @Override
    public void update(BigDecimal amount) {
        System.out.println("Risk Management notified for payment: " + amount);
    }
}

class LoggingObserver implements Observer {
    @Override
    public void update(BigDecimal amount) {
        System.out.println("Logging payment transaction: " + amount);
    }
}

// 主方法
public class Main {
    public static void main(String[] args) {
        PaymentSystemServiceImpl paymentService = new PaymentSystemServiceImpl();
        paymentService.registerObserver(new RiskManagementObserver());
        paymentService.registerObserver(new LoggingObserver());

        PaymentStrategy creditCardStrategy = new CreditCardPaymentStrategy();
        PaymentStrategy payPalStrategy = new PayPalPaymentStrategy();

        SinglePayment creditCardPayment = new SinglePayment(new ConcretePaymentCommand(creditCardStrategy, new BigDecimal("50.0"), paymentService));
        SinglePayment payPalPayment = new SinglePayment(new ConcretePaymentCommand(payPalStrategy, new BigDecimal("25.0"), paymentService));

        CompositePayment compositePayment = new CompositePayment();
        compositePayment.addPayment(creditCardPayment);
        compositePayment.addPayment(payPalPayment);

        paymentService.processPayments(compositePayment);
    }
}

引入命令+组合模式后的分析

现在完整的类图:

这个类图包括以下部分:

  • Observer 和 Subject 接口,分别表示观察者和主题的基本结构
  • PaymentCommand和ConcretePaymentCommand 类,实现命令模式。 PaymentStrategy 接口及其具体实现类
  • CreditCardPaymentStrategy 和 PayPalPaymentStrategy,表示不同的支付策略
  • PaymentComponent 接口及其实现类 SinglePayment 和 CompositePayment,体现组合模式
  • PaymentSystemServiceImpl 类,实现了 Subject 接口,同时处理支付命令
  • RiskManagementObserver 和 LoggingObserver 类,作为观察者实现特定的通知逻辑

混合模式设计的系统优势

  1. 增强的灵活性和可扩展性
    • 策略模式允许动态更换支付逻辑,适应新的支付方式
    • 命令模式通过将请求封装为对象,提供了根据不同情况使用不同请求的灵活性
    • 组合模式使客户端能以统一方式处理单一支付和组合支付,简化客户端使用
  2. 解耦和模块化
    • 观察者模式将通知逻辑从主业务逻辑中解耦,简化了通知类型的添加和修改
    • 策略模式命令模式的应用进一步解耦了支付处理逻辑,增强了模块化
  3. 提高代码的可维护性
    • 模式的应用降低了系统的整体复杂性,使代码更清晰易维护
    • 系统的不同部分可以独立变化,减少了相互间的影响
  4. 更好地遵循软件设计原则
    • 混合模式设计遵循了单一职责原则、开放封闭原则等
    • 提高了系统的可测试性和可靠性

通过这种混合模式设计,支付系统不仅变得更加灵活和可扩展,而且更易于管理和维护。这为应对不断变化的业务需求和技术挑战提供了坚实的基础

写在最后

比起写代码,写文章确实很难,一方面时间精力有限,一方面难以直接将工作代码放在这里,只能自己去编写示例,难免会有疏漏,可能不是特别准确。但总体相信,一定可以给你带来一些思想上的启发。

通过混合使用策略模式、命令模式、组合模式和观察者模式,成功地构建了一个灵活、可扩展且易于维护的支付系统。这种设计不仅提高了系统的模块化和解耦,还优化了支付处理和通知机制,确保了代码的清晰性和可维护性。这些模式的结合展示了如何有效地应对复杂系统设计中的常见挑战,同时保持代码的整洁性与扩展性

希望这篇文章能够为你提供有价值的见解,并帮助你在未来的项目中应用这些设计模式。

我是程序员三毛,如果您觉得这篇文章对您有帮助,请不吝点赞、关注和收藏。您的支持是我不断前进的动力!

  • 程序员三毛
相关推荐
烟沙九洲19 分钟前
算法的时间复杂度
java·算法
写bug写bug29 分钟前
小小 Stream,一篇文章拿捏它
java·后端
写bug写bug33 分钟前
好用的Lombok注解
java·后端
码熔burning1 小时前
【NIO番外篇】之组件 Selector
java·io·nio·selector
triticale1 小时前
【数论】线性筛质数
java·算法
百锦再1 小时前
Android ImageView 使用详解
android·java·app·手机·安卓·studio
续亮~2 小时前
提示词 (Prompt)
java·人工智能·prompt·ai编程·springai
aiden:)2 小时前
设计模式之工厂模式(factory pattern):在商品对象创建系统中的应用
java·开发语言·设计模式·软件工程·软件构建
Tdm_8882 小时前
SQL Server中OPENJSON + WITH 来解析JSON
java·数据库·sql·c#·json·mssql
C137的本贾尼2 小时前
Java内部类详解
java·开发语言