DDD设计模式例子

  1. 样本架(Rack):实体,有唯一ID,包含多个样本(Sample)。

  2. 样本(Sample):值对象或实体(如果有唯一标识,例如样本编号)。

  3. 站点(Station):实体,代表一个处理单元,如分注站、离心站、检测站等。每个站点有唯一ID,并有状态(空闲、忙碌、故障等)。

  4. 流水线(Pipeline):可以看作是一个领域概念,由一系列站点组成,但调度逻辑可能不直接是流水线,而是调度器。

  5. 调度器(Scheduler):领域服务,负责根据当前状态和规则决定样本架的下一个站点。

  6. 传输带(Conveyor):基础设施,负责实际移动样本架。在领域模型中,我们可能只关心调度的逻辑,而实际移动由基础设施服务实现。

限界上下文:整个调度系统作为一个上下文,可能还需要与实验室信息管理系统(LIMS)交互,但这里我们聚焦在调度本身。

战术设计:

  • 实体:Rack, Station, 可能还有Sample(如果样本有独立调度需求,但通常调度的是样本架)。

  • 值对象:位置(Location),可能包括站点位置和传输带上的位置。

  • 领域服务:Scheduler,负责调度决策。

  • 领域事件:当样本架到达某个站点、离开站点、站点状态变化时,可能产生事件,用于触发后续操作。

  • 仓库:RackRepository, StationRepository,用于持久化。

  • 聚合根:Rack和Station可能是聚合根,因为它们有全局标识,并且需要保证一致性边界。

由于我们只是模拟调度逻辑,实际移动由外部控制,我们可以将传输带视为基础设施服务,由它来实际移动样本架,但调度器只做决策。

cpp 复制代码
// 领域模型核心定义
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <functional>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <algorithm>

namespace Domain {

// ===================== 值对象 (Value Objects) =====================
// 值对象是不可变的,通过值进行比较

// 位置坐标
class Location {
public:
    Location(int x, int y, int z = 0) : x_(x), y_(y), z_(z) {}
    
    int getX() const { return x_; }
    int getY() const { return y_; }
    int getZ() const { return z_; }
    
    bool operator==(const Location& other) const {
        return x_ == other.x_ && y_ == other.y_ && z_ == other.z_;
    }
    
    bool operator!=(const Location& other) const {
        return !(*this == other);
    }
    
    std::string toString() const {
        return "(" + std::to_string(x_) + "," + std::to_string(y_) + "," + std::to_string(z_) + ")";
    }
    
private:
    int x_;
    int y_;
    int z_;
};

// 样本架ID - 值对象
class RackId {
public:
    explicit RackId(const std::string& id) : id_(id) {}
    
    const std::string& getId() const { return id_; }
    
    bool operator==(const RackId& other) const { return id_ == other.id_; }
    bool operator!=(const RackId& other) const { return !(*this == other); }
    bool operator<(const RackId& other) const { return id_ < other.id_; }
    
private:
    std::string id_;
};

// 站点ID - 值对象
class StationId {
public:
    explicit StationId(const std::string& id) : id_(id) {}
    
    const std::string& getId() const { return id_; }
    
    bool operator==(const StationId& other) const { return id_ == other.id_; }
    bool operator!=(const StationId& other) const { return !(*this == other); }
    
private:
    std::string id_;
};

// 调度优先级
enum class Priority {
    HIGH = 0,
    NORMAL = 1,
    LOW = 2
};

// 样本架状态
enum class RackStatus {
    IDLE,           // 空闲
    LOADED,         // 已装载样本
    PROCESSING,     // 处理中
    WAITING,        // 等待传输
    TRANSFERRING,   // 传输中
    COMPLETED,      // 处理完成
    ERROR           // 错误
};

// ===================== 实体 (Entities) =====================
// 实体有唯一标识,通过标识进行比较

// 样本实体
class Sample {
public:
    Sample(const std::string& id, const std::string& type, Priority priority = Priority::NORMAL)
        : id_(id), type_(type), priority_(priority), status_(RackStatus::IDLE) {}
    
    const std::string& getId() const { return id_; }
    const std::string& getType() const { return type_; }
    Priority getPriority() const { return priority_; }
    RackStatus getStatus() const { return status_; }
    
    void setStatus(RackStatus status) { status_ = status; }
    
private:
    std::string id_;        // 唯一标识
    std::string type_;      // 样本类型
    Priority priority_;     // 处理优先级
    RackStatus status_;     // 当前状态
};

// 样本架实体 - 聚合根
class Rack : public std::enable_shared_from_this<Rack> {
public:
    Rack(const RackId& id, int capacity = 10) 
        : id_(id), capacity_(capacity), currentLocation_(0, 0, 0), status_(RackStatus::IDLE) {}
    
    const RackId& getId() const { return id_; }
    RackStatus getStatus() const { return status_; }
    const Location& getLocation() const { return currentLocation_; }
    int getSampleCount() const { return static_cast<int>(samples_.size()); }
    int getCapacity() const { return capacity_; }
    
    // 业务方法
    void loadSample(const Sample& sample) {
        if (samples_.size() < capacity_) {
            samples_.push_back(sample);
            if (status_ == RackStatus::IDLE) {
                status_ = RackStatus::LOADED;
            }
        } else {
            throw std::runtime_error("Rack is at full capacity");
        }
    }
    
    void updateLocation(const Location& newLocation) {
        currentLocation_ = newLocation;
        if (status_ == RackStatus::WAITING) {
            status_ = RackStatus::TRANSFERRING;
        }
    }
    
    void setStatus(RackStatus status) { 
        status_ = status; 
    }
    
    void startProcessing() { status_ = RackStatus::PROCESSING; }
    void completeProcessing() { status_ = RackStatus::COMPLETED; }
    
    std::vector<Sample> getSamples() const { return samples_; }
    
    // 检查是否可以处理
    bool canProcess() const {
        return status_ == RackStatus::LOADED || status_ == RackStatus::WAITING;
    }
    
private:
    RackId id_;
    int capacity_;
    Location currentLocation_;
    RackStatus status_;
    std::vector<Sample> samples_;
};

// 站点实体
class Station {
public:
    Station(const StationId& id, const std::string& name, const Location& location, 
            const std::vector<std::string>& supportedSampleTypes)
        : id_(id), name_(name), location_(location), 
          supportedSampleTypes_(supportedSampleTypes), isActive_(true) {}
    
    const StationId& getId() const { return id_; }
    const std::string& getName() const { return name_; }
    const Location& getLocation() const { return location_; }
    bool isActive() const { return isActive_; }
    
    // 业务方法:站点是否支持处理该样本架
    bool canProcessRack(const std::shared_ptr<Rack>& rack) const {
        if (!isActive_) return false;
        
        auto samples = rack->getSamples();
        for (const auto& sample : samples) {
            if (std::find(supportedSampleTypes_.begin(), 
                          supportedSampleTypes_.end(), 
                          sample.getType()) == supportedSampleTypes_.end()) {
                return false;
            }
        }
        return true;
    }
    
    void activate() { isActive_ = true; }
    void deactivate() { isActive_ = false; }
    
private:
    StationId id_;
    std::string name_;
    Location location_;
    std::vector<std::string> supportedSampleTypes_;
    bool isActive_;
};

// ===================== 领域服务 (Domain Services) =====================
// 处理跨多个实件的业务逻辑

// 调度策略接口
class ISchedulingStrategy {
public:
    virtual ~ISchedulingStrategy() = default;
    
    // 决定下一个要处理的样本架
    virtual std::shared_ptr<Rack> selectNextRack(
        const std::vector<std::shared_ptr<Rack>>& availableRacks) = 0;
    
    // 为样本架选择目标站点
    virtual StationId selectTargetStation(
        const std::shared_ptr<Rack>& rack,
        const std::vector<std::shared_ptr<Station>>& availableStations) = 0;
};

// 基于优先级的调度策略
class PrioritySchedulingStrategy : public ISchedulingStrategy {
public:
    std::shared_ptr<Rack> selectNextRack(
        const std::vector<std::shared_ptr<Rack>>& availableRacks) override {
        
        if (availableRacks.empty()) return nullptr;
        
        // 优先选择有高优先级样本的样本架
        auto it = std::max_element(availableRacks.begin(), availableRacks.end(),
            [](const auto& a, const auto& b) {
                auto samplesA = a->getSamples();
                auto samplesB = b->getSamples();
                
                // 简单的优先级比较:检查是否有高优先级样本
                bool aHasHigh = std::any_of(samplesA.begin(), samplesA.end(),
                    [](const Sample& s) { return s.getPriority() == Priority::HIGH; });
                bool bHasHigh = std::any_of(samplesB.begin(), samplesB.end(),
                    [](const Sample& s) { return s.getPriority() == Priority::HIGH; });
                
                if (aHasHigh && !bHasHigh) return false;
                if (!aHasHigh && bHasHigh) return true;
                
                // 如果优先级相同,选择样本多的
                return samplesA.size() < samplesB.size();
            });
        
        return *it;
    }
    
    StationId selectTargetStation(
        const std::shared_ptr<Rack>& rack,
        const std::vector<std::shared_ptr<Station>>& availableStations) override {
        
        for (const auto& station : availableStations) {
            if (station->canProcessRack(rack)) {
                return station->getId();
            }
        }
        
        throw std::runtime_error("No suitable station found for rack");
    }
};

// ===================== 仓储接口 (Repository Interfaces) =====================
// 定义数据访问契约

class IRackRepository {
public:
    virtual ~IRackRepository() = default;
    
    virtual void add(const std::shared_ptr<Rack>& rack) = 0;
    virtual void remove(const RackId& id) = 0;
    virtual std::shared_ptr<Rack> getById(const RackId& id) = 0;
    virtual std::vector<std::shared_ptr<Rack>> getAll() = 0;
    virtual std::vector<std::shared_ptr<Rack>> getByStatus(RackStatus status) = 0;
    virtual void update(const std::shared_ptr<Rack>& rack) = 0;
};

class IStationRepository {
public:
    virtual ~IStationRepository() = default;
    
    virtual void add(const std::shared_ptr<Station>& station) = 0;
    virtual std::shared_ptr<Station> getById(const StationId& id) = 0;
    virtual std::vector<std::shared_ptr<Station>> getAll() = 0;
    virtual std::vector<std::shared_ptr<Station>> getActiveStations() = 0;
};

// ===================== 领域事件 (Domain Events) =====================

class DomainEvent {
public:
    virtual ~DomainEvent() = default;
    virtual std::string getName() const = 0;
    virtual std::string toString() const = 0;
};

class RackStatusChangedEvent : public DomainEvent {
public:
    RackStatusChangedEvent(const RackId& rackId, RackStatus oldStatus, RackStatus newStatus)
        : rackId_(rackId), oldStatus_(oldStatus), newStatus_(newStatus),
          timestamp_(std::chrono::system_clock::now()) {}
    
    std::string getName() const override { return "RackStatusChangedEvent"; }
    
    std::string toString() const override {
        auto time = std::chrono::system_clock::to_time_t(timestamp_);
        char timeStr[20];
        std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", std::localtime(&time));
        
        return "Rack " + rackId_.getId() + " status changed from " + 
               std::to_string(static_cast<int>(oldStatus_)) + " to " +
               std::to_string(static_cast<int>(newStatus_)) + " at " + timeStr;
    }
    
    const RackId& getRackId() const { return rackId_; }
    RackStatus getOldStatus() const { return oldStatus_; }
    RackStatus getNewStatus() const { return newStatus_; }
    
private:
    RackId rackId_;
    RackStatus oldStatus_;
    RackStatus newStatus_;
    std::chrono::system_clock::time_point timestamp_;
};

class RackMovedEvent : public DomainEvent {
public:
    RackMovedEvent(const RackId& rackId, const Location& from, const Location& to)
        : rackId_(rackId), from_(from), to_(to),
          timestamp_(std::chrono::system_clock::now()) {}
    
    std::string getName() const override { return "RackMovedEvent"; }
    
    std::string toString() const override {
        auto time = std::chrono::system_clock::to_time_t(timestamp_);
        char timeStr[20];
        std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", std::localtime(&time));
        
        return "Rack " + rackId_.getId() + " moved from " + 
               from_.toString() + " to " + to_.toString() + " at " + timeStr;
    }
    
private:
    RackId rackId_;
    Location from_;
    Location to_;
    std::chrono::system_clock::time_point timestamp_;
};

// 事件处理器接口
class IEventHandler {
public:
    virtual ~IEventHandler() = default;
    virtual void handle(const std::shared_ptr<DomainEvent>& event) = 0;
};

// 简单的事件总线
class EventBus {
public:
    void subscribe(const std::string& eventName, std::shared_ptr<IEventHandler> handler) {
        subscribers_[eventName].push_back(handler);
    }
    
    void publish(const std::shared_ptr<DomainEvent>& event) {
        auto it = subscribers_.find(event->getName());
        if (it != subscribers_.end()) {
            for (auto& handler : it->second) {
                handler->handle(event);
            }
        }
    }
    
private:
    std::unordered_map<std::string, std::vector<std::shared_ptr<IEventHandler>>> subscribers_;
};

// ===================== 应用服务 (Application Service) =====================
// 协调领域对象完成用例

class RackSchedulingService {
public:
    RackSchedulingService(
        std::shared_ptr<IRackRepository> rackRepo,
        std::shared_ptr<IStationRepository> stationRepo,
        std::shared_ptr<ISchedulingStrategy> strategy,
        std::shared_ptr<EventBus> eventBus)
        : rackRepository_(rackRepo), stationRepository_(stationRepo),
          schedulingStrategy_(strategy), eventBus_(eventBus) {}
    
    // 用例:调度样本架到下一个站点
    bool scheduleRackToNextStation(const RackId& rackId) {
        try {
            // 1. 获取样本架
            auto rack = rackRepository_->getById(rackId);
            if (!rack) {
                std::cerr << "Rack not found: " << rackId.getId() << std::endl;
                return false;
            }
            
            // 2. 检查样本架状态
            if (!rack->canProcess()) {
                std::cerr << "Rack cannot be processed: " << rackId.getId() << std::endl;
                return false;
            }
            
            // 3. 获取可用的站点
            auto availableStations = stationRepository_->getActiveStations();
            if (availableStations.empty()) {
                std::cerr << "No active stations available" << std::endl;
                return false;
            }
            
            // 4. 使用策略选择目标站点
            StationId targetStationId = schedulingStrategy_->selectTargetStation(rack, availableStations);
            auto targetStation = stationRepository_->getById(targetStationId);
            
            if (!targetStation) {
                std::cerr << "Target station not found: " << targetStationId.getId() << std::endl;
                return false;
            }
            
            // 5. 记录旧位置,更新样本架位置和状态
            Location oldLocation = rack->getLocation();
            rack->updateLocation(targetStation->getLocation());
            rack->setStatus(RackStatus::WAITING);
            
            // 6. 保存更新
            rackRepository_->update(rack);
            
            // 7. 发布领域事件
            eventBus_->publish(std::make_shared<RackMovedEvent>(
                rackId, oldLocation, targetStation->getLocation()));
            
            std::cout << "Scheduled rack " << rackId.getId() 
                     << " to station " << targetStationId.getId() << std::endl;
            
            return true;
            
        } catch (const std::exception& e) {
            std::cerr << "Scheduling failed: " << e.what() << std::endl;
            return false;
        }
    }
    
    // 用例:处理样本架
    bool processRack(const RackId& rackId) {
        auto rack = rackRepository_->getById(rackId);
        if (!rack) return false;
        
        RackStatus oldStatus = rack->getStatus();
        rack->startProcessing();
        rackRepository_->update(rack);
        
        // 发布状态变更事件
        eventBus_->publish(std::make_shared<RackStatusChangedEvent>(
            rackId, oldStatus, rack->getStatus()));
        
        // 模拟处理过程
        std::this_thread::sleep_for(std::chrono::seconds(1));
        
        oldStatus = rack->getStatus();
        rack->completeProcessing();
        rackRepository_->update(rack);
        
        eventBus_->publish(std::make_shared<RackStatusChangedEvent>(
            rackId, oldStatus, rack->getStatus()));
        
        std::cout << "Processed rack: " << rackId.getId() << std::endl;
        return true;
    }
    
    // 用例:自动调度下一个样本架
    RackId scheduleNextRack() {
        auto availableRacks = rackRepository_->getByStatus(RackStatus::LOADED);
        if (availableRacks.empty()) {
            throw std::runtime_error("No racks available for scheduling");
        }
        
        auto nextRack = schedulingStrategy_->selectNextRack(availableRacks);
        if (!nextRack) {
            throw std::runtime_error("Failed to select next rack");
        }
        
        if (scheduleRackToNextStation(nextRack->getId())) {
            return nextRack->getId();
        }
        
        throw std::runtime_error("Failed to schedule selected rack");
    }
    
private:
    std::shared_ptr<IRackRepository> rackRepository_;
    std::shared_ptr<IStationRepository> stationRepository_;
    std::shared_ptr<ISchedulingStrategy> schedulingStrategy_;
    std::shared_ptr<EventBus> eventBus_;
};

} // namespace Domain

// ===================== 基础设施层 (Infrastructure Layer) =====================
// 实现仓储接口,提供具体技术实现

namespace Infrastructure {

// 内存实现的仓储
class InMemoryRackRepository : public Domain::IRackRepository {
public:
    void add(const std::shared_ptr<Domain::Rack>& rack) override {
        racks_[rack->getId()] = rack;
    }
    
    void remove(const Domain::RackId& id) override {
        racks_.erase(id);
    }
    
    std::shared_ptr<Domain::Rack> getById(const Domain::RackId& id) override {
        auto it = racks_.find(id);
        return it != racks_.end() ? it->second : nullptr;
    }
    
    std::vector<std::shared_ptr<Domain::Rack>> getAll() override {
        std::vector<std::shared_ptr<Domain::Rack>> result;
        for (const auto& pair : racks_) {
            result.push_back(pair.second);
        }
        return result;
    }
    
    std::vector<std::shared_ptr<Domain::Rack>> getByStatus(Domain::RackStatus status) override {
        std::vector<std::shared_ptr<Domain::Rack>> result;
        for (const auto& pair : racks_) {
            if (pair.second->getStatus() == status) {
                result.push_back(pair.second);
            }
        }
        return result;
    }
    
    void update(const std::shared_ptr<Domain::Rack>& rack) override {
        racks_[rack->getId()] = rack;
    }
    
private:
    std::unordered_map<Domain::RackId, std::shared_ptr<Domain::Rack>, 
        std::hash<std::string>> racks_;
};

class InMemoryStationRepository : public Domain::IStationRepository {
public:
    void add(const std::shared_ptr<Domain::Station>& station) override {
        stations_[station->getId()] = station;
    }
    
    std::shared_ptr<Domain::Station> getById(const Domain::StationId& id) override {
        auto it = stations_.find(id);
        return it != stations_.end() ? it->second : nullptr;
    }
    
    std::vector<std::shared_ptr<Domain::Station>> getAll() override {
        std::vector<std::shared_ptr<Domain::Station>> result;
        for (const auto& pair : stations_) {
            result.push_back(pair.second);
        }
        return result;
    }
    
    std::vector<std::shared_ptr<Domain::Station>> getActiveStations() override {
        std::vector<std::shared_ptr<Domain::Station>> result;
        for (const auto& pair : stations_) {
            if (pair.second->isActive()) {
                result.push_back(pair.second);
            }
        }
        return result;
    }
    
private:
    std::unordered_map<Domain::StationId, std::shared_ptr<Domain::Station>,
        std::hash<std::string>> stations_;
};

// 简单的事件处理器实现
class LoggingEventHandler : public Domain::IEventHandler {
public:
    void handle(const std::shared_ptr<Domain::DomainEvent>& event) override {
        std::cout << "[EVENT] " << event->toString() << std::endl;
    }
};

} // namespace Infrastructure

// ===================== 主程序示例 =====================

int main() {
    using namespace Domain;
    using namespace Infrastructure;
    
    std::cout << "=== 流水线样本架调度系统 (DDD设计) ===\n" << std::endl;
    
    // 1. 初始化基础设施
    auto rackRepo = std::make_shared<InMemoryRackRepository>();
    auto stationRepo = std::make_shared<InMemoryStationRepository>();
    auto schedulingStrategy = std::make_shared<PrioritySchedulingStrategy>();
    auto eventBus = std::make_shared<EventBus>();
    
    // 2. 注册事件处理器
    auto logger = std::make_shared<LoggingEventHandler>();
    eventBus->subscribe("RackStatusChangedEvent", logger);
    eventBus->subscribe("RackMovedEvent", logger);
    
    // 3. 创建应用服务
    RackSchedulingService schedulingService(rackRepo, stationRepo, 
                                           schedulingStrategy, eventBus);
    
    // 4. 初始化领域对象
    // 创建站点
    stationRepo->add(std::make_shared<Station>(
        StationId("ST001"), "样本准备站", Location(0, 0, 0),
        std::vector<std::string>{"BLOOD", "URINE"}
    ));
    
    stationRepo->add(std::make_shared<Station>(
        StationId("ST002"), "离心站", Location(10, 0, 0),
        std::vector<std::string>{"BLOOD"}
    ));
    
    stationRepo->add(std::make_shared<Station>(
        StationId("ST003"), "检测站", Location(20, 0, 0),
        std::vector<std::string>{"BLOOD", "URINE", "CSF"}
    ));
    
    // 创建样本架并装载样本
    auto rack1 = std::make_shared<Rack>(RackId("RACK001"));
    rack1->loadSample(Sample("SMP001", "BLOOD", Priority::HIGH));
    rack1->loadSample(Sample("SMP002", "BLOOD", Priority::NORMAL));
    rack1->setStatus(RackStatus::LOADED);
    
    auto rack2 = std::make_shared<Rack>(RackId("RACK002"));
    rack2->loadSample(Sample("SMP003", "URINE", Priority::NORMAL));
    rack2->setStatus(RackStatus::LOADED);
    
    auto rack3 = std::make_shared<Rack>(RackId("RACK003"));
    rack3->loadSample(Sample("SMP004", "BLOOD", Priority::HIGH));
    rack3->loadSample(Sample("SMP005", "CSF", Priority::HIGH));
    rack3->setStatus(RackStatus::LOADED);
    
    // 添加到仓储
    rackRepo->add(rack1);
    rackRepo->add(rack2);
    rackRepo->add(rack3);
    
    std::cout << "系统初始化完成,共创建:" << std::endl;
    std::cout << "- 站点: " << stationRepo->getAll().size() << " 个" << std::endl;
    std::cout << "- 样本架: " << rackRepo->getAll().size() << " 个" << std::endl;
    std::cout << std::endl;
    
    // 5. 执行业务用例
    std::cout << "=== 开始调度样本架 ===" << std::endl;
    
    try {
        // 调度下一个样本架
        auto nextRackId = schedulingService.scheduleNextRack();
        std::cout << "已调度样本架: " << nextRackId.getId() << std::endl;
        
        // 处理样本架
        schedulingService.processRack(nextRackId);
        
        // 调度第二个样本架
        auto nextRackId2 = schedulingService.scheduleNextRack();
        std::cout << "已调度样本架: " << nextRackId2.getId() << std::endl;
        
    } catch (const std::exception& e) {
        std::cerr << "调度错误: " << e.what() << std::endl;
    }
    
    // 6. 显示最终状态
    std::cout << "\n=== 最终状态 ===" << std::endl;
    auto allRacks = rackRepo->getAll();
    for (const auto& rack : allRacks) {
        std::cout << "样本架 " << rack->getId().getId() 
                  << " - 状态: " << static_cast<int>(rack->getStatus())
                  << " - 位置: " << rack->getLocation().toString()
                  << " - 样本数: " << rack->getSampleCount() << std::endl;
    }
    
    return 0;
}

目录结构示意图:

pipeline_scheduler/

├── include/

│ └── domain/

│ ├── value_objects/ # 值对象

│ │ ├── location.h

│ │ ├── rack_id.h

│ │ └── station_id.h

│ ├── entities/ # 实体

│ │ ├── sample.h

│ │ ├── rack.h

│ │ └── station.h

│ ├── repositories/ # 仓储接口

│ │ ├── irack_repository.h

│ │ └── istation_repository.h

│ ├── services/ # 领域服务

│ │ ├── ischeduling_strategy.h

│ │ └── priority_scheduling_strategy.h

│ ├── events/ # 领域事件

│ │ ├── domain_event.h

│ │ ├── rack_status_changed_event.h

│ │ └── event_bus.h

│ └── application/ # 应用服务

│ └── rack_scheduling_service.h

├── src/

│ ├── domain/ # 领域层实现

│ │ └── entities/

│ │ ├── sample.cpp

│ │ ├── rack.cpp

│ │ └── station.cpp

│ ├── infrastructure/ # 基础设施层

│ │ ├── inmemory_rack_repository.cpp

│ │ ├── inmemory_station_repository.cpp

│ │ └── logging_event_handler.cpp

│ ├── application/ # 应用层实现

│ │ └── rack_scheduling_service.cpp

│ └── main.cpp

├── tests/ # 单元测试

└── CMakeLists.txt

DDD设计要点说明

  1. 领域层(Domain):包含了核心业务逻辑

    • 值对象:LocationRackIdStationId

    • 实体:SampleRack(聚合根)、Station

    • 领域服务:ISchedulingStrategy和其实现

    • 领域事件:DomainEvent及其子类

  2. 应用层(Application)

    • RackSchedulingService:协调领域对象完成特定用例
  3. 基础设施层(Infrastructure)

    • 仓储的内存实现

    • 事件处理器的具体实现

  4. 依赖倒置原则

    • 高层模块(应用服务)依赖抽象(仓储接口)

    • 具体实现在基础设施层

  5. 限界上下文

    • 调度上下文:处理样本架的调度逻辑

    • 可以扩展其他上下文:样本管理、仪器控制等

扩展建议

  1. 添加仓储的数据库实现:替换内存实现为数据库持久化

  2. 实现更复杂的调度策略:基于时间、优先级、仪器负载等

  3. 添加领域事件处理:如样本架完成处理时自动触发下一步调度

  4. 实现CQRS模式:将查询和命令分离,提高查询性能

  5. 添加单元测试:针对每个领域对象和服务的测试

  6. 集成消息队列:用于处理异步领域事件

  7. 添加防腐层:如果需要与其他系统集成

最佳实践总结

  1. 保持聚合小巧:一个聚合只包含必须一起修改的对象

  2. 通过ID引用其他聚合:避免直接对象引用

  3. 最终一致性:跨聚合的业务规则通过领域事件实现最终一致性

  4. 聚合根是门卫:所有修改必须通过聚合根的方法

  5. 聚合根是事务边界:设计时要考虑并发控制

  6. 聚合根包含业务规则:封装最重要的不变量

相关推荐
山沐与山2 小时前
【设计模式】Python观察者模式:用RabbitMQ+Celery实现事件驱动
python·观察者模式·设计模式·rabbitmq
会飞的架狗师12 小时前
DDD笔记 | 实体、值对象、聚合、聚合根
设计模式·设计规范
wanghowie1 天前
01.08 Java基础篇|设计模式深度解析
java·开发语言·设计模式
syt_10131 天前
设计模式之-中介者模式
设计模式·中介者模式
明洞日记1 天前
【设计模式手册023】外观模式 - 如何简化复杂系统
java·设计模式·外观模式
游戏23人生1 天前
c++ 语言教程——16面向对象设计模式(五)
开发语言·c++·设计模式
watersink1 天前
Agent 设计模式
开发语言·javascript·设计模式
老朱佩琪!1 天前
Unity策略模式
unity·设计模式·策略模式
o0向阳而生0o1 天前
116、23种设计模式之责任链模式(23/23)(完结撒花)
设计模式·责任链模式