程序员必备的十大技能(进阶版)之设计模式与架构思维(四)

简介: 教程来源 https://ltglu.cn/ 架构思维聚焦系统级设计:分层架构强调职责分离与上下依赖;六边形架构通过端口/适配器解耦核心业务与外部环境;CQRS分离读写模型提升性能与可维护性;事件驱动架构则以异步事件实现服务松耦合。

五、架构思维:从代码到系统

设计模式解决的是类级别的问题,而架构思维解决的是系统级别的问题。

5.1 架构设计的核心原则
image.png
5.2 分层架构(Layered Architecture)

分层架构(经典四层):
  ┌─────────────────────────────────────┐
  │         表现层 (Presentation)        │  ← Controller, JSP, REST API
  ├─────────────────────────────────────┤
  │         应用层 (Application)         │  ← Service, 业务编排
  ├─────────────────────────────────────┤
  │         领域层 (Domain)              │  ← Entity, 核心业务逻辑
  ├─────────────────────────────────────┤
  │         基础设施层 (Infrastructure)   │  ← Repository, 数据库访问
  └─────────────────────────────────────┘

依赖方向: 上层依赖下层,下层对上层无感知
// 分层架构示例
// 表现层
@RestController
public class OrderController {
    @Autowired
    private OrderApplicationService orderService;

    @PostMapping("/orders")
    public OrderResponse createOrder(@RequestBody CreateOrderRequest request) {
        return orderService.createOrder(request);
    }
}

// 应用层
@Service
public class OrderApplicationService {
    @Autowired
    private OrderDomainService orderDomainService;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private PaymentGateway paymentGateway;

    @Transactional
    public OrderResponse createOrder(CreateOrderRequest request) {
        // 应用层编排
        Order order = Order.create(request.getUserId(), request.getItems());

        // 调用领域服务
        orderDomainService.calculateDiscount(order);

        // 调用基础设施
        orderRepository.save(order);

        // 外部系统调用
        PaymentResult payment = paymentGateway.charge(order.getTotalAmount());

        order.markAsPaid(payment.getTransactionId());
        orderRepository.save(order);

        return OrderResponse.from(order);
    }
}

// 领域层
public class Order {
    private String orderId;
    private String userId;
    private List<OrderItem> items;
    private OrderStatus status;
    private BigDecimal totalAmount;

    // 领域逻辑(核心业务规则)
    public static Order create(String userId, List<OrderItem> items) {
        Order order = new Order();
        order.orderId = generateOrderId();
        order.userId = userId;
        order.items = items;
        order.status = OrderStatus.PENDING;
        order.totalAmount = calculateTotal(items);
        return order;
    }

    public void markAsPaid(String transactionId) {
        if (this.status != OrderStatus.PENDING) {
            throw new IllegalStateException("Order cannot be paid: status is " + this.status);
        }
        this.status = OrderStatus.PAID;
        // 记录支付信息...
    }
}

// 基础设施层
@Repository
public class OrderRepository {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void save(Order order) {
        jdbcTemplate.update("INSERT INTO orders ...", order.getOrderId(), ...);
    }
}

5.3 六边形架构(Hexagonal Architecture / 端口适配器)
六边形架构强调业务逻辑与外部系统的隔离,通过端口(Port)和适配器(Adapter)实现。

┌─────────────────────────────────────────────────────────────────┐
│                        六边形架构                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌─────────────┐                    ┌─────────────┐           │
│   │  HTTP适配器  │                    │ 数据库适配器 │           │
│   └──────┬──────┘                    └──────┬──────┘           │
│          │                                   │                  │
│          ▼                                   ▼                  │
│   ┌─────────────────────────────────────────────────┐         │
│   │                    端口                         │         │
│   │  ┌─────────────────────────────────────────┐   │         │
│   │  │            业务核心(领域模型)          │   │         │
│   │  └─────────────────────────────────────────┘   │         │
│   │                    端口                         │         │
│   └─────────────────────────────────────────────────┘         │
│          ▲                                   ▲                  │
│          │                                   │                  │
│   ┌──────┴──────┐                    ┌──────┴──────┐           │
│   │ 消息适配器   │                    │ 邮件适配器   │           │
│   └─────────────┘                    └─────────────┘           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
// 端口接口(内)
public interface OrderService {
    Order createOrder(OrderCommand command);
    Order getOrder(String orderId);
    void cancelOrder(String orderId);
}

public interface PaymentService {
    PaymentResult charge(BigDecimal amount, PaymentMethod method);
}

// 领域模型(核心业务)
public class Order {
    // 纯业务逻辑,不依赖任何外部框架
    private String id;
    private List<OrderLine> lines;
    private OrderStatus status;

    public void addItem(Product product, int quantity) {
        lines.add(new OrderLine(product, quantity));
        recalculateTotal();
    }

    public void cancel() {
        if (status == OrderStatus.SHIPPED) {
            throw new IllegalStateException("Cannot cancel shipped order");
        }
        this.status = OrderStatus.CANCELLED;
    }

    private void recalculateTotal() {
        this.total = lines.stream()
            .map(line -> line.getProduct().getPrice().multiply(BigDecimal.valueOf(line.getQuantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

// 端口实现(外)
@RestController
public class OrderController implements OrderService {  // 实现端口接口
    private final OrderApplication orderApp;

    @Override
    @PostMapping("/orders")
    public Order createOrder(@RequestBody OrderCommand command) {
        return orderApp.createOrder(command);
    }
}

@Repository
public class OrderRepository implements OrderPort {  // 另一个端口实现
    // 数据库访问逻辑
}

5.4 CQRS(命令查询职责分离)
CQRS将读操作和写操作分离为不同的模型。

// 命令(写模型)
public class CreateOrderCommand {
    private String userId;
    private List<OrderItemDto> items;
}

@Service
public class OrderCommandService {
    @Autowired
    private OrderRepository writeRepository;
    @Autowired
    private EventPublisher eventPublisher;

    @Transactional
    public String handle(CreateOrderCommand command) {
        // 写模型关注业务规则和事务一致性
        Order order = Order.create(command.getUserId(), command.getItems());
        order.validate();

        writeRepository.save(order);

        // 发布领域事件,用于更新读模型
        eventPublisher.publish(new OrderCreatedEvent(order.getId()));

        return order.getId();
    }
}

// 查询(读模型)
@RestController
public class OrderQueryService {
    @Autowired
    private OrderReadRepository readRepository;  // 可以是Elasticsearch或其他

    @GetMapping("/orders/{id}")
    public OrderReadModel getOrder(@PathVariable String id) {
        // 读模型可以完全去规范化,优化查询性能
        return readRepository.findById(id);
    }

    @GetMapping("/orders")
    public Page<OrderReadModel> listOrders(OrderQueryParams params) {
        // 复杂的查询和聚合
        return readRepository.search(params);
    }
}

// 读模型(去规范化)
@Document(indexName = "orders")
public class OrderReadModel {
    private String id;
    private String userId;
    private String userName;       // 冗余用户姓名,避免JOIN
    private List<OrderItemReadModel> items;
    private String status;
    private LocalDateTime createdAt;
    // 不需要所有业务字段,只存查询需要的字段
}

5.5 事件驱动架构(Event-Driven Architecture)
事件驱动架构通过异步事件解耦服务间的通信。

// 领域事件定义
public abstract class DomainEvent {
    private final String eventId = UUID.randomUUID().toString();
    private final LocalDateTime occurredAt = LocalDateTime.now();

    public String getEventId() { return eventId; }
    public LocalDateTime getOccurredAt() { return occurredAt; }
}

public class OrderCreatedEvent extends DomainEvent {
    private final String orderId;
    private final String userId;
    private final BigDecimal amount;

    public OrderCreatedEvent(String orderId, String userId, BigDecimal amount) {
        this.orderId = orderId;
        this.userId = userId;
        this.amount = amount;
    }
    // getters
}

public class OrderPaidEvent extends DomainEvent {
    private final String orderId;
    private final String transactionId;
    // ...
}

// 事件发布器
@Service
public class DomainEventPublisher {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;

    @EventListener
    public void handleDomainEvent(DomainEvent event) {
        // 本地事件(同一JVM内)
        applicationEventPublisher.publishEvent(event);

        // 分布式事件(跨服务)
        kafkaTemplate.send("order-events", event.getClass().getSimpleName(), event);
    }
}

// 事件处理器(本地)
@Component
@EventListener
public class InventoryEventHandler {
    public void handleOrderPaid(OrderPaidEvent event) {
        // 扣减库存
        inventoryService.deductStock(event.getOrderId());
    }
}

// 事件处理器(远程)
@Component
@KafkaListener(topics = "order-events")
public class NotificationEventHandler {
    @KafkaHandler
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 发送确认邮件
        emailService.sendOrderConfirmation(event.getUserId(), event.getOrderId());
    }

    @KafkaHandler
    public void handleOrderPaid(OrderPaidEvent event) {
        // 发送支付成功通知
        notificationService.sendPaymentNotification(event.getUserId());
    }
}

来源:
https://xbivx.cn/

相关文章
|
3月前
|
设计模式 架构师 Java
程序员必备的十大技能(进阶版)之设计模式与架构思维(一)
教程来源 https://rvtst.cn/ 本文系统讲解设计模式与架构思维,涵盖SOLID原则、创建型/结构型/行为型模式实战、DDD、分层/六边形/微服务架构等十大维度,助你从写代码进阶到设计系统。
|
3月前
|
关系型数据库 API 数据库
App Inventor接入Supabase:开源免费的后端新选择
App Inventor开发者福音!Supabase是开源Firebase替代品,基于PostgreSQL,支持实时订阅、自动API、文件存储与认证,可自部署、免费额度足。对比CloudBase,更适配海外场景与高可控需求,零服务器即可接入专业后端。(239字)
366 3
|
3月前
|
存储 人工智能 弹性计算
基于阿里Qoder的实训案例荣获2026全国高校程序设计教育大会特等奖
复旦大学赵卫东老师主持的“基于阿里Qoder开发个人博客系统”实训案例,获2026全国高校程序设计教育大会特等奖。案例融合通义灵码与千问API,覆盖AI写作、分析、部署全流程, exemplifies AI时代产教融合新范式。(239字)
425 3
|
3月前
|
机器学习/深度学习 人工智能 API
5款靠谱的IP归属地查询服务深度测评:准确率、性能、离线库谁更强?
本文实测5款IP归属地查询工具,直击城市级定位不准痛点:广告投放偏差、风控失效。建议:先通过服务商提供的的免费测试额度验证区县级定位效果,用真实业务样本对比竞品差异,再决定是否接入离线库。高精度不是概念,而是可落地的工程能力。
872 2
|
3月前
|
Arthas 缓存 安全
【Java并发编程】高频实战:死锁排查、线程安全问题定位、线程dump分析(附《思维导图》+《面试高频考点清单》)
本文系统梳理Java并发编程高频实战知识:涵盖死锁排查(Coffman四条件、jstack/Arthas分析)、线程安全定位(竞态/可见性/有序性问题及原子类、Lock、ThreadLocal等方案)与线程Dump深度解析(状态识别、死锁/锁竞争/死循环模式)。
|
3月前
|
设计模式 Java 调度
【Java并发编程】锁机制:AQS抽象队列同步器:核心原理、CLH队列、独占/共享模式、基于AQS实现的组件(CountDownLatch、CyclicBarrier等)(附《思维导图》+《面试高频考点清单》)
AQS(AbstractQueuedSynchronizer)是Java并发包(JUC)的基石框架,基于volatile state状态变量与CLH双向等待队列,通过模板方法模式支持独占/共享同步语义,为ReentrantLock、Semaphore、CountDownLatch等核心组件提供统一底层实现。
|
3月前
|
人工智能 监控 JavaScript
2026年制造业AI转型:三个最值得投入的方向
制造业AI落地三个方向:人+Agent混合组织、AI智能数据治理、企业本体语义模型,建议分阶段推进。
|
3月前
|
存储 人工智能 数据库
2026年购买阿里云服务器一年多少钱?38元1年起,最新热门实例与配置活动价格参考
2026年阿里云服务器价格参考:轻量应用服务器2核2G、200M带宽抢购价低至38元/年,2核4G为199元/年;经济型e实例2核2G、3M带宽99元/年(新老同享、续费同价);u1实例2核4G、5M带宽199元/年(企业专享);u2i实例4核8G起1252.63元/年,c9i实例8核16G起5958.52元/年。另有99元/199元"99计划"长期可用,搭配学生券、AI算力券等权益可进一步降本,个人开发者与企业均能找到适配方案。
|
3月前
|
人工智能 前端开发 数据可视化
股票财报分析系统的开发费用
本系统是纯可视化、无表格、AI驱动的股票财报分析工具,费用取决于数据源(免费数百元/年 vs 商业授权5万+)、AI文本生成(LLM调用成本)、定制图表开发(ECharts/AntV动效)及安全合规要求。预算从3万(个人MVP)到百万级(金融机构)不等,前端可视化占30%为最大投入。