Fluent Builder 模式
前言
以前最讨厌设计复杂方法调用, 就是那种需要一堆有逻辑规则的 config 作为参数的方法.
这种 config 通常是一个大对象, 有许多 property, property 之间有存在一些逻辑, 比如当 property A 是什么的时候 B 必须也是什么.
如果不管它, 那么调用方法的人就会很幸苦, 一直到 runtime 才会报错.
Fluent Builder 模式
Fluent Builder 模式就是用来有条有理的创建复杂对象的. 比如上面说到的 config.
很多地方都可以看到它的影子.
EF Core 和 OData 都用了这个方式来创建 model.
FluentValidation 也是用了这个方式来创建 validation rules
如何实现
其内部原理就是通过几个小的 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 模式的更多相关文章
- Joshua Bloch错了? ——适当改变你的Builder模式实现
注:这一系列都是小品文.它们偏重的并不是如何实现模式,而是一系列在模式实现,使用等众多方面绝对值得思考的问题.如果您仅仅希望知道一个模式该如何实现,那么整个系列都会让您失望.如果您希望更深入地了解各个 ...
- effective java 3th item2:考虑 builder 模式,当构造器参数过多的时候
yiaz 读书笔记,翻译于 effective java 3th 英文版,可能有些地方有错误.欢迎指正. 静态工厂方法和构造器都有一个限制:当有许多参数的时候,它们不能很好的扩展. 比如试想下如下场景 ...
- Builder模式在Java中的应用
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
- 创建型模式之Builder模式及实现
建造者(Builder)模式 GOF给出的定义为:建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 应用场景 使用建造者模式是为了将构建复杂对象的过程和它的部件 ...
- Builder模式
原文来源于http://www.iteye.com/topic/71175 对于Builder模式很简单,但是一直想不明白为什么要这么设计,为什么要向builder要Product而不是向知道建造过程 ...
- Android Builder模式在开发中的应用
最近在学习图片加载框架Glide的时候,被他精简的写法震惊了.一句话,就可以搞定. Glide.with(mContext) .load(url) .centerCrop() .placeholder ...
- JAVA Builder模式构建MAP/LIST的示例
我们在构建一个MAP时,要不停的调用put,有时候看着觉得很麻烦,刚好,看了下builder模式,觉得这思路不错,于是乎,照着用builder模式写了一个构建MAP的示例,代码如下: import j ...
- [转]C++设计模式:Builder模式
Builder模式要解决的问题是,当我们要创建很复杂的对象时,有时候需要将复杂对象的创建过程和这个对象的表示分离开来.由于在每一步的构造过程中可以映入不同参数,所以步骤相同但是最后的对象却不一样.也就 ...
- Android设计模式源码解析之Builder模式
https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/builder/mr. ...
- Builder模式(建造者模式)
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成.那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Build ...
随机推荐
- LLM-01 大模型 本地部署运行 ChatGLM2-6B-INT4(6GB) 简单上手 环境配置 单机单卡多卡 2070Super8GBx2 打怪升级!
搬迁说明 之前在 CSDN 上发文章,一直想着努力发一些好的文章出来!这篇文章在 2024-04-17 10:11:55 已在 CSDN 发布 写在前面 其他显卡环境也可以!但是最少要有8GB的显存, ...
- MySQL 递归查询实践总结
MySQL复杂查询使用实例 By:授客 QQ:1033553122 表结构设计 SELECT id, `name`, parent_id FROM `tb_testcase_suite` 说明: ...
- vue项目锚点定位+滚动定位
功能: HTML: js: scrollEvent(e) { let scrollItems = document.querySelectorAll('.condition-container') f ...
- Java---杂记
1. 当System.out.println()方法的参数是Object类型时,println()方法会自动调用Object对象的toString()方法,然后显示toString()方法返回的字符串 ...
- 寻路数据集 —— PathFinding数据集 —— Moving AI Lab. 实验室
好几个做pathfinding的论文都是引用这个网站的数据集,不过这个网站的数据集的地图都是 .map 格式,这个类型的格式该如何打开还不知道. Moving AI Lab. 实验室的工作 地址: h ...
- How to evaluate the Messi Hong Kong fraud incident?
Who is Lionel Messi? URL: https://en.wikipedia.org/wiki/Lionel_Messi As a famous football player, Me ...
- 很好用的python游戏环境(续):强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境
相关: 很好用的python游戏环境:强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境 前文分享了一个python下的maze游戏环境,本文再给出一 ...
- Ubuntu18.04环境下安装网络代理软件 proxychains
安装: 网络代理软件proxychains安装: sudo apt-get install proxychains 为保证使用 proxychains 时 sudo proxychains 时可以实现 ...
- [JLOI2015] 城池攻占 题解
前言 题目链接:洛谷. 题目分析 其他人要么倍增,要么左偏树,那我就来讲讲朴实无华的 dfs 序加上线段树的做法. 首先发现题目中明确指出了作乘法的时候一定是乘上一个大于零的数,这是为什么呢?首先把可 ...
- SpringBoot项目中HTTP请求体只能读一次?试试这方案
问题描述 在基于Spring开发Java项目时,可能需要重复读取HTTP请求体中的数据,例如使用拦截器打印入参信息等,但当我们重复调用getInputStream()或者getReader()时,通常 ...