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

news2024/11/24 15:03:33

引言

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

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

目录

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

案例分析

支付系统概述

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

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

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

初始代码

①定义Payment实体类:

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接口:

import java.util.List;

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

③定义PaymentSystemServiceImpl实现类:

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);
        }
    }
}

④模拟调用

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…:

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类:

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 ...
}

③模拟调用

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);
    }
}

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

先看下当前代码的类图结构:
引入策略模式后的uml 类图
这个类图包括以下部分:

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

存在的问题点:

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

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

引入观察者模式

观察者模式介绍

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

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

引入策略模式后的代码

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)等操作,增加系统的灵活性
  • 组合模式:适用于处理组合支付场景,即在单次交易中使用多种支付方式。允许客户端以统一的方式处理单个支付组合支付,简化了客户端的使用。提高了代码的结构清晰度和可扩展性

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

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. 更好地遵循软件设计原则
    • 混合模式设计遵循了单一职责原则、开放封闭原则等
    • 提高了系统的可测试性和可靠性

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

写在最后

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

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

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

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

  • 程序员三毛

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1343480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Vscode远程debug报错找不到Module找不到File

1..报第一个错 提示我无法导入自己写的module 如图&#xff1a; 解决办法&#xff1a; stackoverflow上说的在launch.json中加了一条 env&#xff0c;就解决了。 "env": { "PYTHONPATH":"/home/zt/ge-sc-master/ge-sc-master"}, 2.解决完第一个…

机器学习的一般步骤

机器学习专注于让机器从大量的数据中模拟人类思考和归纳总结的过程&#xff0c;获得计算模型并自动判断和推测相应的输出结果。机器学习的一般步骤可以概括为以下几个阶段&#xff1a; 数据收集和准备&#xff1a; 收集与问题相关的数据&#xff0c;并确保数据的质量和完整性。…

k8s的陈述式资源管理

k8s的陈述式资源管理&#xff1a; 命令行&#xff1a;kubectl命令行工具 优点&#xff1a;90%以上的场景都可以满足 对资源的增&#xff0c;删&#xff0c;查比较方便&#xff0c;对改不是很友好 缺点&#xff1a; 命令比较冗长&#xff0c;复杂&#xff0c;难记 声明式&…

Adobe 设计精髓:创新的用户体验 | 开源日报 No.130

adobe/react-spectrum Stars: 10.1k License: Apache-2.0 React Spectrum Libraries 是一系列的库和工具&#xff0c;旨在帮助开发者构建适应性强、可访问性好且稳健的用户体验。 核心优势&#xff1a; 提供全面的可访问性和行为支持&#xff0c;符合 WAI-ARIA 编写实践&…

nginx+rsyslog+kafka+clickhouse+grafana 实现nginx 网关监控

需求 我想做一个类似腾讯云网关日志最终以仪表方式呈现&#xff0c;比如说qps、p99、p95的请求响应时间等等 流程图 数据流转就像标题 nginx ----> rsyslog ----> kafka —> clickhouse —> grafana 部署 kafka kafka 相关部署这里不做赘述&#xff0c;只要创…

hyperf console 执行

一、原理描述 hyperf中&#xff0c;不难发现比如自定义控制器中获取参数&#xff0c;hyperf.php中容器获取&#xff0c;传入的都是接口&#xff0c;而不是实体类。 这是因为框架中的配置文件有设置对应抽象类的子类&#xff0c;框架加载的时候将其作为数组&#xff0c;使用的…

楼宇智慧能源消耗监测管理系统,楼宇中的能源“管家”

随着人口的增加&#xff0c;楼宇数据呈上涨趋势&#xff0c;但是楼宇智能建设在我国普及性远远不足&#xff0c;相比传统楼宇控制&#xff0c;智能楼宇控制系统对于楼宇内部的用电设备控制&#xff0c;能够更加的节约能源&#xff0c;降低成本。对于现代化楼宇而言&#xff0c;…

大数据学习(29)-Spark Shuffle

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

代码质量评价及设计原则

1.评价代码质量的标准 1.1 可维护性 可维护性强的代码指的是: 在不去破坏原有的代码设计以及不引入新的BUG的前提下,能够快速的修改或者新增代码. 不易维护的代码指的是: 在添加或者修改一些功能逻辑的时候,存在极大的引入新的BUG的风险,并且需要花费的时间也很长. 代码可…

winserver2008 r2服务器iis配置支持flv,f4v,mp4格式视频

很多政府单位网站一直在使用WIN服务器&#xff0c;大部分网站都使用多年基本使用.NET或者CMS系统建站&#xff0c;系统环境也一直是老版本&#xff0c;今天在维护过程中又出现了新问题&#xff0c;上传的MP4文件不支持网站上播放&#xff0c;顺便也分享下解决过程。当我们架设的…

分布式系统架构设计之分布式系统架构演进和版本管理

在分布式系统的生命周期中&#xff0c;架构演进和版本管理是很重要的两个环节。本部分会介绍分布式系统架构演进的原则、策略以及版本管理的最佳实践&#xff0c;以帮助研发团队更好地应对需求变化、技术发展和系统升级。 架构演进 演进原则 渐进式演进 采用渐进式演进的原…

【51单片机系列】DS1302时钟模块扩展实验之与EEPROM结合使用只进行一次初始化工作

本文是关于时钟芯片DS1302的扩展实验。 文章目录 一、实验分析二、proteus仿真原理图三、软件设计及结果 本实验实现的目的&#xff1a;利用AT24C02掉电不丢失的功能&#xff0c;存储数据用来辨别DS1302时钟是否已经初始化&#xff0c;如果初始化就不执行DS1302初始化函数。 一…

HTML实战演练之贪吃蛇美食大作战

导入&#xff1a; 一 &#xff1a;粉丝要求 今天一位小伙伴私信我说&#xff0c;想玩HTML贪吃蛇美食大作战&#xff0c;自己也是学HTML的&#xff0c;希望我能安排一下&#xff0c;那么好它来了 需知&#xff1a; 一&#xff1a;别着急先看需要知道的 要用HTML开发贪吃蛇美食…

腾讯云服务器租用价格表和优惠活动大全

腾讯云服务器租用价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月&#xff0c;云服务器CVM S5实例2核2G配置280.8元一年…

Vue(二):计算属性与 watch 监听器

03. Vue 指令拓展 3.1 指令修饰符 可以通过 . 来指明一些指令的后缀&#xff0c;不同的后缀中封装了不同的操作&#xff0c;可以帮助我们简化代码&#xff0c;比如之前使用过的监听 enter 键的弹起&#xff0c;我们需要操作事件对象&#xff0c;来检测用户使用了哪个键&#…

亚马逊云科技Amazon MSK基于S3云服务器实现导出导入、备份还原、迁移方案

亚马逊云科技Amazon MSK是Amazon云平台提供的托管Kafka服务。在系统升级或迁移时&#xff0c;用户常常需要将一个Amazon MSK集群中的数据导出&#xff08;备份&#xff09;&#xff0c;然后在新集群或另一个集群中再将数据导入&#xff08;还原&#xff09;。通常&#xff0c;K…

【网络安全 | CTF】FlatScience

该题考察SQL注入 正文 后台扫到robots.txt 页面内容如下&#xff1a; 进入login.php 页面源代码如图&#xff1a; 传参debug得到php代码&#xff1a; <?php if(isset($_POST[usr]) && isset($_POST[pw])){$user $_POST[usr];$pass $_POST[pw];$db new SQLite3…

Linux(ubuntu)下git / github/gitee使用

先附上git命令 linuxchenxiao:~$ cd Templates/ 先进入一个目录&#xff0c;也可mkdir新建一个目录&#xff1a;用于接下来初始化为git可以管理的仓库 这个目录就是所说的工作目录&#xff0c;指当前正在进行开发的项目的本地目录。 linuxchenxiao:~/Templates$ git init 已…

Web自动化测试:Selenium入门到精通

前言 说到自动化测试&#xff0c;就不得不提大名鼎鼎的Selenium。Selenium 是如今最常用的自动化测试工具之一&#xff0c;支持快速开发自动化测试框架&#xff0c;且支持在多种浏览器上执行测试。 Selenium学习难度小&#xff0c;开发周期短。对测试人员来说&#xff0c;如果…

C# 使用ZXing.Net生成二维码和条码

写在前面 条码生成是一个经常需要处理的功能&#xff0c;本文介绍一个条码处理类库&#xff0c;ZXing用Java实现的多种格式的一维二维条码图像处理库&#xff0c;而ZXing.Net是其.Net版本的实现。 在WinForm下使用该类库需要从NuGet安装两个组件&#xff1a; ZXing.Net ZXing…