美文网首页
17.领域服务

17.领域服务

作者: 鸿雁长飞光不度 | 来源:发表于2022-08-23 20:29 被阅读0次

表示一个无状态的操作,用于实现某个特定的领域任务,某些操作不适合放在聚合和值对象上就用领域服务,它是无状态的,表示领域中具有显著流程的行为。

1.理解领域服务

领域服务代表了领域的概念,是问题域中的行为,与领域专家对话中产生,肯定是通用语言的一部分。比如计价认证

1.1 何时使用领域服务

某些行为不适合放在任何一个实体中,尝试强制归属实体时就该考虑用领域服务了。

  1. 封装业务策略和过程

用领域服务执行一些设计实体或者值对象的行为,比如一个Competitor表示参与玩家,OnlineDeathMatch表示比赛,规则是玩家参与比赛结束后分别会获取不同的分数,如果不用领域服务一般会将比赛分数结算规则放在OnlineDeathMatch实体的方法中,如果奖励本身比较复杂,可以定义一个奖励结算类,不同的规则可以叠加。得分和奖励本身是重要的概念,下面案例表示封装了积分结算的单依职责的领域服务。

package main

import "fmt"

type Competitor struct {
    Id    int64
    Score int
    Name  string
    Rank  int
}

// 表示计算分数的规则
type IScoreApply interface {
    Apply(IGame)
}

// 普通规则
type NormalScoreRule struct {
}

func (r *NormalScoreRule) Apply(game IGame) {

    var amount = 200
    if game.Winner() != nil {
        game.Winner().Score += amount
    }
    if game.Loser() != nil {
        game.Loser().Score -= amount
    }
}

// 如果对手是前10名的,胜利者加100分
type ExtraRewardRule struct {
}

func (r *ExtraRewardRule) Apply(game IGame) {
    var amount = 100
    if game.Winner() != nil && game.Loser().Rank < 100 {
        game.Winner().Score += amount
    }
}

type IGame interface {
    Winner() *Competitor
    Loser() *Competitor
}
type OnlineDeathMatch struct {
    player1 *Competitor
    player2 *Competitor

    winner *Competitor
    loser  *Competitor

    scores []IScoreApply
}

func (m *OnlineDeathMatch) Winner() *Competitor {
    return m.loser
}

func (m *OnlineDeathMatch) Loser() *Competitor {
    return m.winner
}

func (m *OnlineDeathMatch) Battle() {
    // 其他逻辑
    m.winner = m.player1
    m.loser = m.player2
    m.updateScoreAndReward()
}

func (m *OnlineDeathMatch) updateScoreAndReward() {
    for _, scoreRule := range m.scores {
        scoreRule.Apply(m)
    }
}

func main() {

    var player1 = &Competitor{
        Id:    1,
        Score: 1000,
        Name:  "one",
        Rank:  50,
    }

    var player2 = &Competitor{
        Id:    2,
        Score: 1000,
        Name:  "two",
        Rank:  60,
    }

    var match = OnlineDeathMatch{
        player1: player1,
        player2: player2,
        scores:  []IScoreApply{&ExtraRewardRule{}, &NormalScoreRule{}},
    }
    match.Battle()

    fmt.Println(player1.Score)
    fmt.Println(player2.Score)

}

2.表示约定

领域中表示约定的一些概念比较重要,但是需要依赖基础架构,在领域模型中是不能使用基础架构的,这部分也要封装成领域服务

  • 税务查询
  • 实时通知
  • 汇率查询

2. 领域服务解析

代表行为、不具备身份、无状态是领域服务的特点。

2.1避免使用贫血领域模型

如果认同了不是所有的行为都应该放在实体上,尝试将所有的行为都拆分到领域服务来实现,会导致领域模型只有数据没有行为、只有一些get和set方法,形成贫血模型,降低模型的内聚性,所以要在领域服务和实体绑定方法之间取一个平衡。

2.2 与应用程序服务对比

领域服务:代表了问题域的概念,接口在领域模型中,有时会依赖用于通知领域逻辑的基础架构
应用程序服务:不代表领域概念,不包含业务规则,基础架构问题是为了让领域模型正确运行。

3.利用领域服务

3.1 在服务层

在应用服务层从存储库提取数据构造实体后传递给领域服务,购物车的商品计价也是类似的例子,接收各种商品、优惠信息然后进行价格计算并输出结果。

image.png

3.2 领域中使用

有时实体需要依赖领域服务实现其行为,比如执行完以后产生一个通知。

// 表示餐品预定实体
type RestaurantBooking struct {
    customerId int64
    confirmed bool
    restaurantId int64
}

type RestaurantNotify struct {
    
}

func (n*RestaurantNotify)NotifyConfirm(restaurantId int64,customerId int64)  {
    
}

func (b*RestaurantBooking)ConfirmBook()  {
    notify := RestaurantNotify{}
    notify.NotifyConfirm(b.restaurantId,b.customerId)
}

如何让RestaurantNotify在RestaurantBooking内部可用有很多实现方式。

  1. 构造方法实现,就是在实例化RestaurantBooking的时候手动传入,但是有的时候可能外接没有必要感知。

  2. 可用工厂方法,工厂方法接收其他参数,在工厂方法内部将RestaurantNotify对象和其他参数一起传递给RestaurantBooking的构造方法。

3.动态依赖注入,PHP里面见过,go语言没有见过实现,可能go的反射性能问题比较大吧,这个的前提还是要将RestaurantNotify放在构造方法中。

4.双向派发

type RestaurantNotify struct {
}

func (n *RestaurantNotify) NotifyConfirm(r *RestaurantBooking) bool {
    return true
}

func (b *RestaurantBooking) ConfirmBook(notify *RestaurantNotify) {
    b.confirmed = notify.NotifyConfirm(b)
}
  1. 使用领域事件

如果需要完全避免将领域服务引入实体,可以由实体发出领域事件,在消息处理的handle方法中根据类型调用领域服务逻辑去处理。

相关文章

  • 17.领域服务

    表示一个无状态的操作,用于实现某个特定的领域任务,某些操作不适合放在聚合和值对象上就用领域服务,它是无状态的,表示...

  • 基于ABP实现DDD--领域服务、应用服务和DTO实践

    什么是领域服务呢?领域服务就是领域对象本身的服务,通常是通过多个聚合以实现单个聚合无法处理的逻辑。 一.领域服务实...

  • 《实现领域驱动设计》拆书稿 第7章 领域服务

    拆书稿 一、什么是领域服务(首先,什么不是领域服务) 领域服务和应用服务的区别 应用服务: 不会处理业务逻辑,它负...

  • 关于建设工程与房地产法学研究会的几点建议

    一、职责定位 1、服务建设领域地方立法; 2、服务建设领域政策研究; 3、服务建设领域依法行政;...

  • 老人领域服务

    大一大二觉得自己毕业后应该会去青少年领域工作,肯定不会做老年人领域,老年人领域气氛太压抑与沉重了 但是经过大三这学...

  • 实现领域驱动设计-领域服务

    领域服务定义 先看看领域服务的定义:领域中的服务表示一个无状态的操作,它用于实现特定于某个领域的任务。当某个操作不...

  • 服务本身也是个产品(其他领域也可以这么思考)

    ipd中围绕两条线,各个领域都可以看做在开发领域子包+领域子业务计划。 如服务领域: 1,服务包:包括可服务性需求...

  • 微服务

    微服务的特点 1:是一系列小服务的组合。微服务粒度围绕业务进行拆分的,(比如:商品领域,交易领域,物流领域) 2:...

  • 架构设计原则

    业务与技术分离 技术组件/库 技术服务 应用与服务分离 领域内应用(主要功能为领域的,可以调用其他领域服务) 跨领...

  • DDD领域驱动开发标准

    领域驱动和微服务的关系 领域驱动和微服务的关系如下图所示: 领域驱动划分微服务的方法论支持,其中限界上下文boun...

网友评论

      本文标题:17.领域服务

      本文链接:https://www.haomeiwen.com/subject/oqmwgrtx.html