前言

以前最讨厌设计复杂方法调用, 就是那种需要一堆有逻辑规则的 config 作为参数的方法.

这种 config 通常是一个大对象, 有许多 property, property 之间有存在一些逻辑, 比如当 property A 是什么的时候 B 必须也是什么.

如果不管它, 那么调用方法的人就会很幸苦, 一直到 runtime 才会报错.

Fluent Builder 模式

Fluent Builder 模式就是用来有条有理的创建复杂对象的. 比如上面说到的 config.

很多地方都可以看到它的影子.

EF Core 和 OData 都用了这个方式来创建 model.

FluentValidation 也是用了这个方式来创建 validation rules

如何实现

参考: Fluent Builder模式简介

其内部原理就是通过几个小的 builder, 每一个 builder 负责一部分创建. 然后串起来.

每一个小 builder 就可以通过方法, 去声明类型, 和限制调用顺序等.

虽然它不能 100% 解决使用者调用错误的问题, 但是已经非常多了.

在设计方法调用的时候, 我们不可以认为使用者是开发人员就顺便的做, 应该要尽可能让调用简单, 智能, 有类型推倒.

before

builder.HasPrincipalProperty(e => e.ProductName, e => e.Color.Product.Name, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
WhereExpression = e => e.Type == SizeType.TypeA,
WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.ProductId, e => e.Color.Product.Id, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
WhereExpression = e => e.Type == SizeType.TypeA,
WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.Age, e => e.Color.Product.Age, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
WhereExpression = e => e.Type == SizeType.TypeA,
WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});

after

builder.HasPrincipalProperty()
.Relation(e => e.Color.Product)
.PropertyMap(e => e.ProductName, e => e.Name)
.PropertyMap(e => e.ProductAge, e => e.Age)
.PropertyMap(e => e.ProductId, e => e.Id)
.Conditional(condition =>
{
condition.WhereExpression = e => e.Type == SizeType.TypeA;
condition.WhenNoInCondition = WhenNoInCondition.SetValueManually;
});

这个例子里面有点复杂, 不适合用作教学, 看看调用自己揣摩一下就好.

Fluent Builder 模式的更多相关文章

  1. Joshua Bloch错了? ——适当改变你的Builder模式实现

    注:这一系列都是小品文.它们偏重的并不是如何实现模式,而是一系列在模式实现,使用等众多方面绝对值得思考的问题.如果您仅仅希望知道一个模式该如何实现,那么整个系列都会让您失望.如果您希望更深入地了解各个 ...

  2. effective java 3th item2:考虑 builder 模式,当构造器参数过多的时候

    yiaz 读书笔记,翻译于 effective java 3th 英文版,可能有些地方有错误.欢迎指正. 静态工厂方法和构造器都有一个限制:当有许多参数的时候,它们不能很好的扩展. 比如试想下如下场景 ...

  3. Builder模式在Java中的应用

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

  4. 创建型模式之Builder模式及实现

    建造者(Builder)模式 GOF给出的定义为:建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 应用场景 使用建造者模式是为了将构建复杂对象的过程和它的部件 ...

  5. Builder模式

    原文来源于http://www.iteye.com/topic/71175 对于Builder模式很简单,但是一直想不明白为什么要这么设计,为什么要向builder要Product而不是向知道建造过程 ...

  6. Android Builder模式在开发中的应用

    最近在学习图片加载框架Glide的时候,被他精简的写法震惊了.一句话,就可以搞定. Glide.with(mContext) .load(url) .centerCrop() .placeholder ...

  7. JAVA Builder模式构建MAP/LIST的示例

    我们在构建一个MAP时,要不停的调用put,有时候看着觉得很麻烦,刚好,看了下builder模式,觉得这思路不错,于是乎,照着用builder模式写了一个构建MAP的示例,代码如下: import j ...

  8. [转]C++设计模式:Builder模式

    Builder模式要解决的问题是,当我们要创建很复杂的对象时,有时候需要将复杂对象的创建过程和这个对象的表示分离开来.由于在每一步的构造过程中可以映入不同参数,所以步骤相同但是最后的对象却不一样.也就 ...

  9. Android设计模式源码解析之Builder模式

    https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/builder/mr. ...

  10. Builder模式(建造者模式)

    在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...

随机推荐

  1. AT_tenka1_2015_qualB_b 题解

    洛谷链接&Atcoder 链接 本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读. 题目简述 给定一个集合形式,判断此集合是 dict 还是 set. 思路 简单的模拟题. 首先需 ...

  2. [rCore学习笔记 09]为内核支持函数调用

    在[[08 内核第一条指令|上一节]]我们使用了编写entry.asm函数中编写了内核的第一条指令,但是我们使用的汇编.这里注意我们仍然是嵌入了这段asm代码到我们的rust代码之中,然后进行编译.但 ...

  3. 由delete语句引起的锁范围扩大

    由delete语句引起的锁范围扩大 阿里云月报中的一句话,出处:http://mysql.taobao.org/monthly/2022/01/01/ 但是Ghost Record是可以跟正常的Rec ...

  4. docker基础学习总结

    docker是一个快速安装部署的容器,快捷简单.可以隔离是他的优点 docker也拥有仓库:dockerhub,存储和管理镜像的平台 我们利用docker安装时就是在里面下载镜像,镜像不仅包含应用本身 ...

  5. Redis的事务transactions与管道pipeline

    1.Redis的事务仅仅是保证事务里的操作会被连续独占的执行,Redis的命令执行是单线程, 2.Redis不保证事务的所有指令可以同时成功或者同时失败,只可以决定是否开始执行全部指令的能力,因此也没 ...

  6. 【Java】Input,Output,Stream I/O流 02 文件流 & 缓冲流

    Reader & Writter 只适合文本的输入输出 [.txt .java .c .cpp] 传输文件,不能使用文本IO进行读写,需要使用文件输入输出流 public class IOTe ...

  7. 【Docker】06 部署挂载本地目录的Nginx

    1.拉取Nginx镜像: docker pull nginx:1.19 2.生成一个测试的Nginx容器: docker run --rm --name nginx-test -p 8080:80 - ...

  8. 从.net开发做到云原生运维(四)——.net core的微服务开发

    1. .net 6.0项目模板变更 在.net 5和.net 3.1的时候,asp.net core项目模板里有个Program类和Startup类,在.net 6中引入了一个最小api的项目模板,在 ...

  9. 人形机器人操作系统(开源) —— FreeRTOS

    地址: https://www.freertos.org/zh-cn-cmn-s/index.html

  10. docker容器挂载host宿主机的本地目录,docker容器与宿主机之间互相拷贝文件

    docker容器挂载host宿主机的本地目录,docker容器与宿主机之间互相拷贝文件 参考于: https://blog.csdn.net/weixin_37773766/article/detai ...