设计模式之:外观模式

文章目录

什么是外观模式?

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。

核心思想

外观模式的核心思想是:提供一个统一的接口,来访问子系统中的多个接口,从而隐藏子系统的复杂性,让客户端更容易使用。

生活中的外观模式

想象一下去餐厅吃饭:

  • 你不需要直接跟厨师、服务员、收银员分别打交道
  • 只需要跟服务员(外观)点餐
  • 服务员会协调后厨、收银等各个部门
  • 你得到的是简单统一的点餐体验

服务员就是整个餐厅系统的"外观"!

模式结构

外观模式包含三个核心角色:

  1. 外观类(Facade):提供统一的接口,知道哪些子系统负责处理请求
  2. 子系统类(Subsystem Classes):实现子系统的功能,处理外观对象指派的任务
  3. 客户端(Client):通过外观接口与子系统交互

基础示例:家庭影院系统

1. 子系统类

java 复制代码
/**
 * 投影仪 - 子系统类
 */
public class Projector {
    public void on() {
        System.out.println("投影仪开启");
    }
    
    public void off() {
        System.out.println("投影仪关闭");
    }
    
    public void setInput(String input) {
        System.out.println("投影仪输入源设置为: " + input);
    }
    
    public void wideScreenMode() {
        System.out.println("投影仪设置为宽屏模式");
    }
}

/**
 * 音响系统 - 子系统类
 */
public class SoundSystem {
    public void on() {
        System.out.println("音响系统开启");
    }
    
    public void off() {
        System.out.println("音响系统关闭");
    }
    
    public void setVolume(int level) {
        System.out.println("音响音量设置为: " + level);
    }
    
    public void setSurroundSound() {
        System.out.println("音响设置为环绕声模式");
    }
}

/**
 * DVD播放器 - 子系统类
 */
public class DvdPlayer {
    public void on() {
        System.out.println("DVD播放器开启");
    }
    
    public void off() {
        System.out.println("DVD播放器关闭");
    }
    
    public void play(String movie) {
        System.out.println("DVD播放器开始播放: " + movie);
    }
    
    public void stop() {
        System.out.println("DVD播放器停止播放");
    }
    
    public void eject() {
        System.out.println("DVD播放器弹出光盘");
    }
}

/**
 * 灯光控制器 - 子系统类
 */
public class LightController {
    public void dim(int level) {
        System.out.println("灯光调暗到: " + level + "%");
    }
    
    public void on() {
        System.out.println("灯光全开");
    }
    
    public void off() {
        System.out.println("灯光关闭");
    }
}

/**
 * 窗帘控制器 - 子系统类
 */
public class CurtainController {
    public void open() {
        System.out.println("窗帘打开");
    }
    
    public void close() {
        System.out.println("窗帘关闭");
    }
}

2. 外观类

java 复制代码
/**
 * 家庭影院外观类 - 外观类
 * 提供简化的接口来控制复杂的家庭影院系统
 */
public class HomeTheaterFacade {
    // 引用所有子系统组件
    private Projector projector;
    private SoundSystem soundSystem;
    private DvdPlayer dvdPlayer;
    private LightController lightController;
    private CurtainController curtainController;
    
    public HomeTheaterFacade(Projector projector, SoundSystem soundSystem,
                           DvdPlayer dvdPlayer, LightController lightController,
                           CurtainController curtainController) {
        this.projector = projector;
        this.soundSystem = soundSystem;
        this.dvdPlayer = dvdPlayer;
        this.lightController = lightController;
        this.curtainController = curtainController;
    }
    
    /**
     * 一键开启电影模式
     */
    public void watchMovie(String movie) {
        System.out.println("🎬 准备观看电影: " + movie);
        System.out.println("=" .repeat(40));
        
        curtainController.close();          // 关闭窗帘
        lightController.dim(10);           // 调暗灯光
        projector.on();                    // 打开投影仪
        projector.setInput("DVD");
        projector.wideScreenMode();
        soundSystem.on();                  // 打开音响
        soundSystem.setSurroundSound();
        soundSystem.setVolume(20);
        dvdPlayer.on();                    // 打开DVD
        dvdPlayer.play(movie);             // 播放电影
        
        System.out.println("=" .repeat(40));
        System.out.println("🎯 电影模式准备就绪!");
    }
    
    /**
     * 一键结束电影
     */
    public void endMovie() {
        System.out.println("🛑 结束电影播放");
        System.out.println("=" .repeat(40));
        
        dvdPlayer.stop();                  // 停止DVD
        dvdPlayer.eject();                 // 弹出光盘
        dvdPlayer.off();                   // 关闭DVD
        soundSystem.off();                 // 关闭音响
        projector.off();                   // 关闭投影仪
        lightController.on();              // 打开灯光
        curtainController.open();          // 打开窗帘
        
        System.out.println("=" .repeat(40));
        System.out.println("✅ 家庭影院系统已关闭");
    }
    
    /**
     * 一键听音乐模式
     */
    public void listenToMusic() {
        System.out.println("🎵 切换到音乐模式");
        System.out.println("=" .repeat(40));
        
        lightController.dim(30);           // 适度调暗灯光
        curtainController.open();          // 打开窗帘
        soundSystem.on();                  // 打开音响
        soundSystem.setVolume(15);
        
        System.out.println("=" .repeat(40));
        System.out.println("🎧 音乐模式准备就绪!");
    }
    
    /**
     * 系统状态检查
     */
    public void systemStatus() {
        System.out.println("📊 系统状态检查:");
        System.out.println("- 投影仪: " + (projector != null ? "就绪" : "未连接"));
        System.out.println("- 音响系统: " + (soundSystem != null ? "就绪" : "未连接"));
        System.out.println("- DVD播放器: " + (dvdPlayer != null ? "就绪" : "未连接"));
        System.out.println("- 灯光控制: " + (lightController != null ? "就绪" : "未连接"));
        System.out.println("- 窗帘控制: " + (curtainController != null ? "就绪" : "未连接"));
    }
}

3. 客户端使用

java 复制代码
/**
 * 家庭影院客户端
 */
public class HomeTheaterClient {
    public static void main(String[] args) {
        System.out.println("=== 家庭影院系统演示 ===\n");
        
        // 创建子系统组件
        Projector projector = new Projector();
        SoundSystem soundSystem = new SoundSystem();
        DvdPlayer dvdPlayer = new DvdPlayer();
        LightController lightController = new LightController();
        CurtainController curtainController = new CurtainController();
        
        // 创建外观对象
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(
            projector, soundSystem, dvdPlayer, lightController, curtainController);
        
        // 检查系统状态
        homeTheater.systemStatus();
        
        System.out.println("\n" + "⭐".repeat(50));
        
        // 使用外观的简单接口
        homeTheater.watchMovie("阿凡达");
        
        System.out.println("\n" + "⭐".repeat(50));
        
        // 模拟观看一段时间后结束
        try {
            Thread.sleep(2000); // 模拟观看2秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        homeTheater.endMovie();
        
        System.out.println("\n" + "⭐".repeat(50));
        
        // 切换到音乐模式
        homeTheater.listenToMusic();
    }
}

完整示例:电商订单系统

让我们通过一个更复杂的电商订单系统来深入理解外观模式。

1. 子系统类

java 复制代码
/**
 * 库存服务 - 子系统类
 */
public class InventoryService {
    public boolean checkStock(String productId, int quantity) {
        System.out.println("📦 检查库存: 商品 " + productId + " 数量 " + quantity);
        // 模拟库存检查
        boolean inStock = Math.random() > 0.1; // 90%有库存
        System.out.println("库存状态: " + (inStock ? "充足" : "缺货"));
        return inStock;
    }
    
    public void updateStock(String productId, int quantity) {
        System.out.println("📦 更新库存: 商品 " + productId + " 减少 " + quantity);
    }
    
    public void lockStock(String productId, int quantity) {
        System.out.println("🔒 锁定库存: 商品 " + productId + " 数量 " + quantity);
    }
}

/**
 * 支付服务 - 子系统类
 */
public class PaymentService {
    public boolean processPayment(String orderId, double amount, String paymentMethod) {
        System.out.println("💳 处理支付: 订单 " + orderId + " 金额 ¥" + amount + " 方式 " + paymentMethod);
        // 模拟支付处理
        boolean success = Math.random() > 0.05; // 95%成功率
        System.out.println("支付结果: " + (success ? "成功" : "失败"));
        return success;
    }
    
    public void refundPayment(String orderId, double amount) {
        System.out.println("🔄 退款处理: 订单 " + orderId + " 金额 ¥" + amount);
    }
}

/**
 * 物流服务 - 子系统类
 */
public class ShippingService {
    public String createShipping(String orderId, String address) {
        System.out.println("🚚 创建物流: 订单 " + orderId + " 地址 " + address);
        String trackingNumber = "TRK" + System.currentTimeMillis();
        System.out.println("物流单号: " + trackingNumber);
        return trackingNumber;
    }
    
    public void schedulePickup(String trackingNumber) {
        System.out.println("📅 安排取件: 物流单号 " + trackingNumber);
    }
    
    public void updateShippingStatus(String trackingNumber, String status) {
        System.out.println("📝 更新物流状态: " + trackingNumber + " -> " + status);
    }
}

/**
 * 通知服务 - 子系统类
 */
public class NotificationService {
    public void sendOrderConfirmation(String orderId, String email) {
        System.out.println("📧 发送订单确认邮件: 订单 " + orderId + " 到 " + email);
    }
    
    public void sendShippingNotification(String orderId, String trackingNumber, String email) {
        System.out.println("📦 发送发货通知: 订单 " + orderId + " 物流单号 " + trackingNumber + " 到 " + email);
    }
    
    public void sendPaymentFailure(String orderId, String email) {
        System.out.println("❌ 发送支付失败通知: 订单 " + orderId + " 到 " + email);
    }
}

/**
 * 优惠券服务 - 子系统类
 */
public class CouponService {
    public boolean validateCoupon(String couponCode, double orderAmount) {
        System.out.println("🎫 验证优惠券: " + couponCode + " 订单金额 ¥" + orderAmount);
        boolean valid = couponCode != null && couponCode.startsWith("DISCOUNT");
        System.out.println("优惠券状态: " + (valid ? "有效" : "无效"));
        return valid;
    }
    
    public double applyCoupon(String couponCode, double orderAmount) {
        System.out.println("💰 应用优惠券: " + couponCode);
        double discount = orderAmount * 0.1; // 10%折扣
        System.out.println("优惠金额: ¥" + discount);
        return orderAmount - discount;
    }
}

2. 订单外观类

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

/**
 * 订单处理外观类
 * 简化订单处理流程,隐藏底层复杂性
 */
public class OrderProcessingFacade {
    private InventoryService inventoryService;
    private PaymentService paymentService;
    private ShippingService shippingService;
    private NotificationService notificationService;
    private CouponService couponService;
    
    public OrderProcessingFacade() {
        this.inventoryService = new InventoryService();
        this.paymentService = new PaymentService();
        this.shippingService = new ShippingService();
        this.notificationService = new NotificationService();
        this.couponService = new CouponService();
    }
    
    /**
     * 一键下单
     */
    public OrderResult placeOrder(OrderRequest request) {
        System.out.println("🛒 开始处理订单: " + request.getOrderId());
        System.out.println("=" .repeat(50));
        
        OrderResult result = new OrderResult(request.getOrderId());
        
        try {
            // 1. 检查库存
            if (!inventoryService.checkStock(request.getProductId(), request.getQuantity())) {
                result.setSuccess(false);
                result.setMessage("商品库存不足");
                return result;
            }
            
            // 2. 验证优惠券
            double finalAmount = request.getAmount();
            if (request.getCouponCode() != null) {
                if (couponService.validateCoupon(request.getCouponCode(), request.getAmount())) {
                    finalAmount = couponService.applyCoupon(request.getCouponCode(), request.getAmount());
                }
            }
            
            // 3. 处理支付
            if (!paymentService.processPayment(request.getOrderId(), finalAmount, request.getPaymentMethod())) {
                result.setSuccess(false);
                result.setMessage("支付处理失败");
                notificationService.sendPaymentFailure(request.getOrderId(), request.getCustomerEmail());
                return result;
            }
            
            // 4. 锁定库存
            inventoryService.lockStock(request.getProductId(), request.getQuantity());
            
            // 5. 创建物流
            String trackingNumber = shippingService.createShipping(request.getOrderId(), request.getShippingAddress());
            shippingService.schedulePickup(trackingNumber);
            
            // 6. 发送通知
            notificationService.sendOrderConfirmation(request.getOrderId(), request.getCustomerEmail());
            notificationService.sendShippingNotification(request.getOrderId(), trackingNumber, request.getCustomerEmail());
            
            // 7. 更新库存
            inventoryService.updateStock(request.getProductId(), request.getQuantity());
            
            result.setSuccess(true);
            result.setMessage("订单处理成功");
            result.setTrackingNumber(trackingNumber);
            result.setFinalAmount(finalAmount);
            
            System.out.println("=" .repeat(50));
            System.out.println("✅ 订单处理完成: " + request.getOrderId());
            
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage("订单处理异常: " + e.getMessage());
            System.out.println("❌ 订单处理失败: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 取消订单
     */
    public boolean cancelOrder(String orderId, double amount) {
        System.out.println("🗑️ 取消订单: " + orderId);
        System.out.println("=" .repeat(50));
        
        try {
            paymentService.refundPayment(orderId, amount);
            System.out.println("✅ 订单取消完成: " + orderId);
            return true;
        } catch (Exception e) {
            System.out.println("❌ 订单取消失败: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 查询订单状态
     */
    public void checkOrderStatus(String orderId, String trackingNumber) {
        System.out.println("🔍 查询订单状态: " + orderId);
        shippingService.updateShippingStatus(trackingNumber, "运输中");
        System.out.println("订单状态: 运输中");
    }
}

/**
 * 订单请求类
 */
class OrderRequest {
    private String orderId;
    private String productId;
    private int quantity;
    private double amount;
    private String paymentMethod;
    private String customerEmail;
    private String shippingAddress;
    private String couponCode;
    
    // 构造函数
    public OrderRequest(String orderId, String productId, int quantity, double amount,
                      String paymentMethod, String customerEmail, String shippingAddress) {
        this.orderId = orderId;
        this.productId = productId;
        this.quantity = quantity;
        this.amount = amount;
        this.paymentMethod = paymentMethod;
        this.customerEmail = customerEmail;
        this.shippingAddress = shippingAddress;
    }
    
    // Getter和Setter方法
    public String getOrderId() { return orderId; }
    public String getProductId() { return productId; }
    public int getQuantity() { return quantity; }
    public double getAmount() { return amount; }
    public String getPaymentMethod() { return paymentMethod; }
    public String getCustomerEmail() { return customerEmail; }
    public String getShippingAddress() { return shippingAddress; }
    public String getCouponCode() { return couponCode; }
    public void setCouponCode(String couponCode) { this.couponCode = couponCode; }
}

/**
 * 订单结果类
 */
class OrderResult {
    private String orderId;
    private boolean success;
    private String message;
    private String trackingNumber;
    private double finalAmount;
    
    public OrderResult(String orderId) {
        this.orderId = orderId;
    }
    
    // Getter和Setter方法
    public String getOrderId() { return orderId; }
    public boolean isSuccess() { return success; }
    public void setSuccess(boolean success) { this.success = success; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    public String getTrackingNumber() { return trackingNumber; }
    public void setTrackingNumber(String trackingNumber) { this.trackingNumber = trackingNumber; }
    public double getFinalAmount() { return finalAmount; }
    public void setFinalAmount(double finalAmount) { this.finalAmount = finalAmount; }
    
    @Override
    public String toString() {
        return String.format("订单%s: %s %s", orderId, 
            success ? "成功" : "失败", message);
    }
}

3. 电商客户端

java 复制代码
/**
 * 电商系统客户端
 */
public class ECommerceClient {
    public static void main(String[] args) {
        System.out.println("=== 电商订单系统演示 ===\n");
        
        // 创建订单处理外观
        OrderProcessingFacade orderProcessor = new OrderProcessingFacade();
        
        // 示例1:正常下单流程
        demonstrateNormalOrder(orderProcessor);
        
        // 示例2:使用优惠券下单
        demonstrateCouponOrder(orderProcessor);
        
        // 示例3:支付失败情况
        demonstratePaymentFailure(orderProcessor);
        
        // 示例4:取消订单
        demonstrateOrderCancellation(orderProcessor);
    }
    
    /**
     * 演示正常下单流程
     */
    private static void demonstrateNormalOrder(OrderProcessingFacade processor) {
        System.out.println("1. 正常下单流程演示:");
        System.out.println("-".repeat(50));
        
        OrderRequest request = new OrderRequest(
            "ORDER_001", "PRODUCT_123", 2, 199.99, 
            "支付宝", "customer@example.com", "北京市朝阳区xxx"
        );
        
        OrderResult result = processor.placeOrder(request);
        System.out.println("下单结果: " + result);
        
        if (result.isSuccess()) {
            System.out.println("物流单号: " + result.getTrackingNumber());
            System.out.println("实付金额: ¥" + result.getFinalAmount());
        }
    }
    
    /**
     * 演示使用优惠券下单
     */
    private static void demonstrateCouponOrder(OrderProcessingFacade processor) {
        System.out.println("\n2. 使用优惠券下单演示:");
        System.out.println("-".repeat(50));
        
        OrderRequest request = new OrderRequest(
            "ORDER_002", "PRODUCT_456", 1, 299.00,
            "微信支付", "vip@example.com", "上海市浦东新区xxx"
        );
        request.setCouponCode("DISCOUNT10");
        
        OrderResult result = processor.placeOrder(request);
        System.out.println("下单结果: " + result);
        
        if (result.isSuccess()) {
            System.out.println("原价: ¥299.00");
            System.out.println("优惠后: ¥" + result.getFinalAmount());
            System.out.println("节省: ¥" + (299.00 - result.getFinalAmount()));
        }
    }
    
    /**
     * 演示支付失败情况
     */
    private static void demonstratePaymentFailure(OrderProcessingFacade processor) {
        System.out.println("\n3. 支付失败情况演示:");
        System.out.println("-".repeat(50));
        
        // 注意:由于支付有5%失败率,可能需要多次运行才能看到失败情况
        OrderRequest request = new OrderRequest(
            "ORDER_003", "PRODUCT_789", 1, 99.50,
            "信用卡", "test@example.com", "广州市天河区xxx"
        );
        
        OrderResult result = processor.placeOrder(request);
        System.out.println("下单结果: " + result);
    }
    
    /**
     * 演示取消订单
     */
    private static void demonstrateOrderCancellation(OrderProcessingFacade processor) {
        System.out.println("\n4. 取消订单演示:");
        System.out.println("-".repeat(50));
        
        boolean success = processor.cancelOrder("ORDER_001", 199.99);
        System.out.println("取消结果: " + (success ? "成功" : "失败"));
    }
}

实际应用示例:银行转账系统

java 复制代码
/**
 * 银行转账系统外观模式示例
 */
public class BankTransferFacade {
    private AccountService accountService;
    private TransferService transferService;
    private NotificationService notificationService;
    private AuditService auditService;
    
    public BankTransferFacade() {
        this.accountService = new AccountService();
        this.transferService = new TransferService();
        this.notificationService = new NotificationService();
        this.auditService = new AuditService();
    }
    
    /**
     * 一键转账
     */
    public boolean transfer(String fromAccount, String toAccount, double amount) {
        System.out.println("💰 开始转账: " + fromAccount + " -> " + toAccount + " 金额 ¥" + amount);
        
        // 1. 验证账户
        if (!accountService.validateAccount(fromAccount) || 
            !accountService.validateAccount(toAccount)) {
            System.out.println("❌ 账户验证失败");
            return false;
        }
        
        // 2. 检查余额
        if (!accountService.checkBalance(fromAccount, amount)) {
            System.out.println("❌ 余额不足");
            return false;
        }
        
        // 3. 执行转账
        if (!transferService.executeTransfer(fromAccount, toAccount, amount)) {
            System.out.println("❌ 转账执行失败");
            return false;
        }
        
        // 4. 记录审计日志
        auditService.logTransfer(fromAccount, toAccount, amount);
        
        // 5. 发送通知
        notificationService.sendTransferNotification(fromAccount, toAccount, amount);
        
        System.out.println("✅ 转账完成");
        return true;
    }
}

// 子系统类
class AccountService {
    public boolean validateAccount(String account) {
        System.out.println("🔍 验证账户: " + account);
        return account.startsWith("ACC");
    }
    
    public boolean checkBalance(String account, double amount) {
        System.out.println("💵 检查余额: " + account + " 金额 ¥" + amount);
        return amount <= 10000; // 简单模拟
    }
}

class TransferService {
    public boolean executeTransfer(String from, String to, double amount) {
        System.out.println("🔄 执行转账: " + from + " -> " + to + " ¥" + amount);
        return Math.random() > 0.02; // 98%成功率
    }
}

class NotificationService {
    public void sendTransferNotification(String from, String to, double amount) {
        System.out.println("📧 发送转账通知: " + from + " 向 " + to + " 转账 ¥" + amount);
    }
}

class AuditService {
    public void logTransfer(String from, String to, double amount) {
        System.out.println("📝 记录审计日志: 转账 " + from + " -> " + to + " ¥" + amount);
    }
}

外观模式的优点

1. 简化客户端使用

java 复制代码
// 没有外观模式:
inventoryService.checkStock();
paymentService.processPayment();
shippingService.createShipping();
notificationService.sendNotification();

// 有外观模式:
orderFacade.placeOrder(); // 一行代码搞定!

2. 解耦客户端与子系统

java 复制代码
// 客户端只依赖外观类
OrderProcessingFacade facade = new OrderProcessingFacade();
// 不直接依赖各个服务类,降低耦合度

3. 易于维护和扩展

java 复制代码
// 修改子系统不影响客户端
public class OrderProcessingFacade {
    // 可以轻松添加新的服务,客户端无感知
    private NewService newService; // 新增服务
}

外观模式的缺点

1. 不符合开闭原则

java 复制代码
// 当需要添加新的功能时,可能需要修改外观类
public class OrderProcessingFacade {
    // 新增功能可能需要修改这个类
}

2. 可能成为上帝对象

java 复制代码
// 如果外观类承担太多职责,可能变得过于复杂
public class GodFacade {
    // 处理所有事情,违反单一职责原则
}

适用场景

  1. 要为复杂的子系统提供简单接口时
  2. 客户端与多个子系统之间存在很多依赖关系时
  3. 需要构建层次结构的子系统时
  4. 希望解耦客户端与子系统时

最佳实践

1. 保持外观类简单

java 复制代码
public class SimpleFacade {
    // 每个外观类应该只关注一个特定的功能领域
    // 不要让它变成"万能"类
}

2. 合理划分外观层次

java 复制代码
// 对于复杂系统,可以使用多个外观类
public class OrderFacade { }        // 订单相关
public class PaymentFacade { }      // 支付相关  
public class ShippingFacade { }     // 物流相关

3. 考虑使用接口

java 复制代码
public interface OrderService {
    OrderResult placeOrder(OrderRequest request);
}

public class OrderFacade implements OrderService {
    // 实现接口,提供更好的灵活性
}

外观模式 vs 其他模式

模式 目的 特点
外观模式 简化接口 提供统一入口,隐藏复杂性
适配器模式 接口转换 使不兼容的接口能够一起工作
中介者模式 协调交互 减少对象间的直接依赖

总结

外观模式就像是一个"总管家",帮你处理所有复杂的事务,让你只需要关注最终结果。

核心价值:

  • 简化复杂系统的使用
  • 降低客户端与子系统的耦合度
  • 提高代码的可维护性

使用场景:

  • 系统有很多复杂的子系统时
  • 想要为子系统提供简单统一的接口时
  • 需要解耦客户端与子系统时

简单记忆:

复杂系统不用愁,外观模式来帮忙!

一个接口管所有,简单方便又高效。

掌握外观模式,能够让你在面对复杂系统时游刃有余,为用户提供简单优雅的使用体验!

相关推荐
乐之者v3 小时前
Mac常用软件
java·1024程序员节
TDengine (老段)3 小时前
TDengine 数据函数 ROUND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·1024程序员节
TDengine (老段)3 小时前
TDengine 数学函数 RAND 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
從南走到北3 小时前
JAVA无人自助共享系统台球室源码自助开台约球交友系统源码小程序
java·微信·微信小程序·小程序·1024程序员节
杯莫停丶3 小时前
设计模式之:命令模式
设计模式·命令模式·1024程序员节·活动勋章
野犬寒鸦3 小时前
从零起步学习MySQL || 第十章:深入了解B+树及B+树的性能优势(结合底层数据结构与数据库设计深度解析)
java·数据库·后端·mysql·1024程序员节
没有bug.的程序员4 小时前
Spring 常见问题与调试技巧
java·后端·spring·动态代理·1024程序员节
Han.miracle4 小时前
数据结构——排序的超级详解(Java版)
java·数据结构·学习·算法·leetcode·排序算法·1024程序员节
毕设源码-朱学姐4 小时前
【开题答辩全过程】以 毕业设计选题系统的设计与实现为例,包含答辩的问题和答案
java·eclipse