工厂模式
类图
模板方法模式
应用场景很多,尤其是在框架设计中,提供了一个方便的开发程序的模板,你只要实现模板中的一些接口或者方法就能完成一个复杂的任务。
结构类图
AbstractTemplate:定义一个完整的框架,方法的调用顺序已经确定,但会定义一些抽象的方法留给子类去实现。
SubTemplate:实现抽象模板中定义的抽象方法,从而形成一个完整的流程逻辑。
123456789101112131415161718192021222324252627282930313233public TradeFlowActionResult execute(TradeFlowActionParam param, Map context) throws ServiceException { try { // 业务逻辑校验 this.validateBusinessLogic(param, context); } catch (ServiceException ex) { sendGoodsLog.info("SendGoodsA ...
策略模式
策略模式通常是指完成某个操作可能会有多种方法,适用于多种场合。我们需要把每个操作方法当作一个实现策略,调用者可根据需要(特定的规则)选择合适的策略。
结构类图
Context:使用不同的策略环境,根据自身的条件选择不同的策略实现类来完成所需要的操作。它持有一个策略实例的引用。
Strategy:抽象策略,定义每个策略都要实现的方法。
Realize1,Realize2:负责实现抽象策略中定义的策略方法。
例子
123456789@Override@Enhancement({@Capability(type = CapabilityTypeEnum.INVOCATION_STATS)})public void sendGoods(SendGoodsParam param) throws ServiceException { if (param == null || param.getId() == null) { this.throwInValidError(ErrorCodeEnum.NULL_PARAM, null, pa ...
装饰模式
装饰者模式,在保持原有功能不变的情况下将一个类重新装饰,使其具有更强大的功能,用一句成语形容“锦上添花”。
类结构:
Component:抽象组件,定义了一组抽象的接口,制定了被修饰的组件都有哪些功能。
ComponentImpl:抽象组件实现类,完成了基本的功能实现。
Decorator:装饰器角色,持有Component的实例引用,有点递归的感觉。
12345678910Component c = new ComponentImpl();Decorator d1 = new Decorator();d1.setComponent(c);Decorator d2 = new Decorator();d2.setComponent(d1);Decorator d3 = new Decorator();d3.setComponent(d2);Decorator d4 = new Decorator();d4.setComponent(d3);d4.methodA();
装饰模式和适配器模式有点类似,都是包装(wrapper)了一个类,但目的却不相同。适配器模式是将一个接口转换成另一个 ...
观察者模式
观察者模式通常也叫 发布-订阅 模式,或者事件监听模式,定义一对多的依赖关系,让多个观察者对象同时监听一个主题对象,如果这个主体对象的状态发生变化时,会通知所有的观察者对象。异步消息(MQ、ActiveMQ)都是基于这种模式。
类结构
Subject:主题类,将所有的观察者对象保存在一个List集合中,并提供增、删方法,以及状态变化后的通知方法。
Observer:观察者的抽象接口,提供了一个抽象的动作方法,具体的业务由子类来实现。
ConcreteObserver:具体的观察者,负责实现自己的业务动作。
ConcreteSubject:具体的主题类,在内部状态发生变化时,给所有登记过的观察者发出通知。
优点
解耦,将耦合的双方都依赖于抽象类,而不是依赖于具体。从而使得各自的变化不会影响到另一边的变化。
Observer采用的是抽象类,这样的好处是可以将多个子类相同的代码逻辑抽取出来,放到抽象类中。
责任链模式
责任链模式就是很多对象由每个对象对其下家的引用串联起来形成一条链,请求在这条链上传递,知道最终处理完。就像一根水管一样,水从一端流入,会经过一系列的阀门,最终从另一端流出。如果有一个阀门关着,水就流不出来。
链上的节点可以控制,根据是否执行分为两种情况:
找到对应的点,执行,跳出。如:for循环的break。
所有的节点都执行一遍,上个节点的返回结果作为下个节点的入参。
业务需求:抽奖
步骤:
抽奖资格判断
判断人群
判断抽奖限制(如每天只能抽3次)
黑名单
判断中奖次数限制(如最多只能中3次) 。。。。。。。。
中奖逻辑
根据用户V等级进行概率过滤
根据抽奖概率进行过滤
发奖逻辑
取出当前奖品分布,并选出一个奖品分布来发奖
减库存
发奖
发奖成功后的逻辑处理
处理其它processor中添加的callback
代码示例 :
主流程:
1234567891011121314151617181920212223242526272829public class Def ...
适配器模式
适配器模式就是一个类的接口不能被客户端接受,需要转换成另一种接口,从而使两个不匹配的接口能在一起工作。
类结构
Adaptee:源接口,需要适配的接口。
Target:目标接口,暴露出去的接口。
Adapter:适配器,将源接口适配成目标接口。
举个例子:
Adaptee是内存卡,Target是电脑,而Adapter则是USB读卡器。
适用场景
比如查物流信息,由于物流公司的系统都是各自独立,而编程语言和交互方式上有很大差异,需要针对不同的物流公司做单独适配,同时结合不同公司的系统性能,配置不同的响应超时时间。
GitHub编程语言色彩一览
资源文件下载:
github-colors.json
github-colors.csv
github-colors.less
github-colors.scss
编程语言色彩一览表:
编程语言
颜色
示例
Mercury
#ff2b2b
TypeScript
#2b7489
PureBasic
#5a6986
Objective-C++
#6866fb
Self
#0579aa
NewLisp
#87AED7
Fortran
#4d41b1
Ceylon
#dfa535
Rebol
#358a5b
Frege
#00cafe
AspectJ
#a957b0
Omgrofl
#cabbff
HolyC
#ffefaf
Shell
#89e051
HiveQL
#dce200
AppleScript
#101F1F
Eiffel
#946d57
XQuery
#5232e7
RUNOFF
#665a4e
RAML
#77d9fb
MTML
#b7e1f ...
从Ultimate-Spider全方位解析数据采集系统的基本知识
Ultimate Spider【终极蜘蛛王】,一款用于网络数据采集的工具。本文对Ultimate Spider的整体架构和一些技术亮点作说明。
Ultimate Spider主要页面有:1、用来展示概览信息的仪表盘页;2、爬虫配置页。
整体架构如下图所示:
爬虫配置在WebMagic爬虫框架的基础上对初始Url和爬取内容进行可视化配置,爬取规则的制定更加灵活多变,适应范围更广。
SpiderProcessor.java 根据爬取规则进行爬取
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495@Slf4j@EnableConfigurationProperties({SpiderProperties.class})public class Spid ...
最佳日志实践
引用自最佳日志实践(v2.0)
什么是日志日志用来记录用户操作、系统运行状态等,是一个系统的重要组成部分。然而,由于日志通常不属于系统的核心功能,所以常常不被团队成员所重视。对于一些简单的小程序,可能并不需要在如何记录日志的问题上花费太多精力。但是对于作为基础平台为很多产品提供服务的后端程序,就必须要考虑如何依靠良好的日志来保证系统可靠的运行了。
好的日志可以帮助系统的开发和运维人员:
了解线上系统的运行状态
快速准确定位线上问题
发现系统瓶颈
预警系统潜在风险
挖掘产品最大价值
……
不好的日志导致:
对系统的运行状态一知半解,甚至一无所知
系统出现问题无法定位,或者需要花费巨大的时间和精力
无法发现系统瓶颈,不知优化从何做起
无法基于日志对系统运行过程中的错误和潜在风险进行监控和报警
对挖掘用户行为和提升产品价值毫无帮助
……
日志的分类日志从功能来说,可分为诊断日志、统计日志、审计日志。
诊断日志, 典型的有:
请求入口和出口
外部服务调用和返回
资源消耗操作: 如读写文件等
容错行为: 如云硬盘的副本修复操作
程序异常: 如数据库无法连接
后台操作:定期执行删 ...
基础组件设计
1、ORM组件设计核心功能
根据ID获取Entity
根据QueryWrapper获取第一个Entity
根据ID集合获取Entity列表
获取所有Entity列表
根据QueryWrapper获取Entity列表
根据IPage分页查询对象获取Entity分页数据
根据IPage分页查询对象和QueryWrapper获取Entity分页数据
保存Entity(ID不存在插入记录,ID存在更新记录)
批量保存Entity
根据ID删除Entity
根据ID集合批量删除Entity
根据Entity集合批量删除Entity
根据ID获取Vo
根据QueryWrapper获取第一个Vo
根据ID集合获取Vo列表
获取所有Vo列表
根据QueryWrapper获取Vo列表
根据IPage分页查询对象获取Vo分页数据
根据IPage分页查询对象和QueryWrapper获取Vo分页数据
保存Dto(ID不存在插入记录,ID存在更新记录)
批量保存Dto
根据ID集合统计数量
根据QueryWrapper统计数量
资源访问鉴权
关键实现逻辑
逻辑删除
解决思路:增加is_deleted字段
...
位运算
位运算即是在位级别进行操作的技术,合适的位运算能够帮助我们得到更快的运算速度与更小的内存使用。
常见的位运算:
测试第k位:s & (1 << k)
设置第k位:s |= (1 << k)
第k位置零:s &= ~(1 << k)
切换第k位值:s ^= ~(1 << k)
乘以2^n:s << n
除以2^n:s >> n
交集:s & t
并集:s | t
减法:s & ~t
交换:x = x ^ y ^ (y = x)
取出最小非0位(Extract lowest set bit):s & (-s)
取出最小0位(Extract lowest unset bit):~s & (s + 1)
交换值:x ^= y; y ^= x; x ^= y;
图算法
深度优先搜索
深度优先算法是一种优先遍历子节点而不是回溯的算法。
时间复杂度: O(|V| + |E|)
广度优先搜索
广度优先搜索是优先遍历邻居节点而不是子节点的图遍历算法。
时间复杂度: O(|V| + |E|)
拓扑排序
拓扑排序是对于有向图节点的线性排序,如果存在某条从 u 到 v 的边,则认为 u 的下标先于 v。
时间复杂度: O(|V| + |E|)
Dijkstra算法
Dijkstra 算法 用于计算有向图中单源最短路径问题。
时间复杂度: O(|V|^2)
Bellman-Ford算法
Bellman-Ford 算法是在带权图中计算从单一源点出发到其他节点的最短路径的算法。
尽管算法复杂度大于 Dijkstra 算法,但是它适用于包含了负值边的图。
时间复杂度:
最优时间: O(|E|)
最坏时间: O(|V||E|)
Floyd-Warshall算法
Floyd-Warshall 算法 能够用于在无环带权图中寻找任意节点的最短路径。
时间复杂度:
最优时间: O(|V|^3)
最坏时间: O(|V|^3)
平均时间: O(|V|^3)
P ...
常见数据结构
Linked List
链表即是由节点(Node)组成的线性集合,每个节点可以利用指针指向其他节点。它是一种包含了多个节点的、能够用于表示序列的数据结构。
单向链表: 链表中的节点仅指向下一个节点,并且最后一个节点指向空。
双向链表: 其中每个节点具有两个指针p、n,使得p指向先前节点并且n指向下一个节点;最后一个节点的n指针指向null。
循环链表: 每个节点指向下一个节点并且最后一个节点指向第一个节点的链表。
时间复杂度:
索引:O(n)
搜索:O(n)
插入:O(1)
移除:O(1)
Stack
栈是元素的集合,其包含了两个基本操作:push操作可以用于将元素压入栈,pop操作可以将栈顶元素移除。
遵循后入先出(LIFO)原则。
时间复杂度:
索引:O(n)
搜索:O(n)
插入:O(1)
移除:O(1)
Queue
队列是元素的集合,其包含了两个基本操作:enqueue操作可以用于将元素插入到队列中,而dequeue操作则是将元素从队列中移除。
遵循先入先出原则(FIFO)。
时间复杂度:
索引:O(n)
搜索:O(n)
插入:O(1)
移除:O(1)
Tre ...
排序算法
插入排序直接插入排序
思想: 每次将一个待排序的数据按照其关键字的大小插入到前面已经排序好的数据中的适当位置,直到全部数据排序完成。
时间复杂度: O(n^2) O(n) O(n^2) (最坏 最好 平均)
空间复杂度: O(1)
稳定性: 稳定,每次都是在前面排好序的序列中找到适当的位置,只有小的数字会往前插入,所以原来相同的两个数字在排序后相对位置不变。
代码示例:
123456789101112//插入排序public static void insertSort(int[] array) { for (int i = 2; i < array.length; i++) { int val = array[i]; int j = i - 1; while (j >= 0 && array[j] > val) { // array[j] > val array[j + 1] = array[j]; j--; ...
CAP理论
CAP理论
引用自 分布式系统的CAP理论
1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。
Consistency
Availability
Partition tolerance它们的第一个字母分别是 C、A、P。
Eric Brewer 说,这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
无论你是一个系统架构师,还是一个普通开发,当你开发或者设计一个分布式系统的时候,CAP理论是无论如何也绕不过去的。本文就来介绍一下到底什么是CAP理论,如何证明CAP理论,以及CAP的权衡问题。
CAP理论概述CAP理论:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
读者需要注意的是,CAP理论中的CA和数据库事务中ACID的CA并不完全是一回事。两者中的C都是一致性(Consistency)。CAP中的A值得是可用性(Availability),而ACID中的A指的是原子性(Atomicity),切勿混为一谈 ...
分布式系统
分布式系统
引用自 大家都在说的分布式系统到底是什么?
随着大型网站的各种高并发访问、海量数据处理等场景越来越多,如何实现网站的高可用、易伸缩、可扩展、安全等目标就显得越来越重要。为了解决这样一系列问题,大型网站的架构也在不断发展。提高大型网站的高可用架构,不得不提的就是分布式。本文主要简单介绍了分布式系统的概念、分布式系统的特点、常用的分布式方案以及分布式和集群的区别等。
集中式系统在学习分布式之前,先了解一下与之相对应的集中式系统是什么样的。
集中式系统用一句话概括就是:一个主机带多个终端。终端没有数据处理能力,仅负责数据的录入和输出。而运算、存储等全部在主机上进行。现在的银行系统,大部分都是这种集中式的系统,此外,在大型企业、科研单位、军队、政府等也有分布。集中式系统,主要流行于上个世纪。
集中式系统的最大的特点就是部署结构非常简单,底层一般采用从IBM、HP等厂商购买到的昂贵的大型主机。因此无需考虑如何对服务进行多节点的部署,也就不用考虑各节点之间的分布式协作问题。但是,由于采用单机部署。很可能带来系统大而复杂、难于维护、发生单点故障(单个点发生故障的时候会波及到整个系统 ...
可容灾分布式系统设计
可容灾分布式系统设计
引用自 后台开发必备知识——容灾 容灾系统的衡量指标和级别有哪些?
基本概念后台开发的目标是要提供高可用的后台服务,其中很重要的一点是保证业务连续性(服务不中断,或中断时间在允许范围内)。要保证业务连续性,系统需要具备容灾能力。
所谓容灾,就是对灾难(disaster)的容忍能力,即在灾难袭来时,能够保证信息系统正常运行而采取的措施,以实现业务连续性为目标。
衡量指标衡量容灾系统的主要指标有RPO(Recovery Point Objective,灾难发生时允许丢失的数据量)、RTO(Recovery Time Objective,系统恢复的时间)、容灾半径(生产系统和容灾系统之间的距离)以及ROI(Return of Investment,容灾系统的投入产出比)。
RPO:业务系统所允许的灾难过程中的最大数据丢失量(以时间来度量),这是一个灾备系统所选用的数据复制技术有密切关系的指标,用以衡量灾备方案的数据冗余备份能力。
RTO:将信息系统从灾难造成的故障或瘫痪状态恢复到可正常运行状态,并将其支持的业务功能从灾难造成的不正常状态恢复到可接收状态所需的时间, ...
幂等操作
幂等操作
引用自 高并发的核心技术-幂等的实现方案
幂等性概念幂等(idempotent、idempotence)是一个数字与计算机学概念,常见于抽象代数中。
在编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,getUsername() 和 setTrue() 函数就是幂等函数。
应用场景以下是一些常见场景:
前端重复提交选中的数据,应该后台只产生对应这个数据的一个响应结果。
我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱。
发送消息,也应该只发一次,同样的短信发给用户,用户会哭的。
创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。
技术方案查询操作查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select是天然的幂等操作。
删除操作删除操作也是幂等的,删除一次和多此删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在 ...
最终一致性
最终一致性
引用自 分布式系统原理九:CAP理论和BASE理论 作者:frank
BASE理论BASE是 Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写。
BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方法来使系统达到最终一致性。接下来,我们着重对BASE中的三要素进行讲解。
基本可用基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性——但请注意,这绝不等价于系统不可用。以下就是两个“基本可用”的例子。
响应时间上的损失:正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了1~2秒。
功能上的损失:正常情况下,在一个电子商务网站(比如淘宝)上购物,消费者几乎能够顺利地完成每一笔订单。但在一些节日大促购物高峰 ...