愿景:"让编程不再难学,让技术与生活更加有趣"
更多架构课程请访问 xdclass.net
目录
第2集 责任链设计模式案例实战-老王设计的反作弊系统的风控级别
第3集 Command Pattern命令设计模式介绍和应用场景
第5集 IteratorPattern迭代器设计模式介绍和应用场景
第1集 责任链设计模式介绍和应用场景
简介:责任链设计模式介绍和应用场景
-
责任链设计模式(Chain of Responsibility Pattern)
- 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象
- 让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条调用链,并沿着这条链传递该请求,直到有一个对象处理它才终止
- 有两个核心行为:一是处理请求,二是将请求传递到下一节点
-
应用场景
- Apache Tomcat 对 Encoding 编码处理的处理,SpringBoot里面的拦截器、过滤器链
- 在请求处理者不明确的情况下向多个对象中的一个提交请求
- 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时刻动态决定的,这种对象就可以使用职责链模式
-
角色
- Handler抽象处理者:定义了一个处理请求的接口
- ConcreteHandler具体处理者: 处理所负责的请求,可访问它的后续节点,如果可处理该请求就处理,否则就将该请求转发给它的后续节点
第2集 责任链设计模式案例实战-老王设计的反作弊系统的风控级别
简介:责任链设计模式案例实战
- 业务需求
风控规则,就是对于每个场景,定义一些规则,来进行相应的控制,比如银行借款、支付宝提现、大额转账等 会触发不同的策略。
像互联网金融行业的话,除了公司内部政策,所处的外部环境经常发生变化,比如国家经常会出政策,这些都经常需要调整相应的风控参数和风控级别。
例子:支付宝转账,根据转账额度不同,会触发的风控级别不一样,1000元以下直接转,1千到1万需要手机号验证码,1万到以上需要刷脸验证。
- 编码实战
public class Request {
/**
* 类别
*/
private String requestType;
/**
* 金额
*/
private int money;
//set get方法省略
}
public enum RequestType {
/**
* 转账
*/
TRANSFER,
/**
* 提现
*/
CASH_OUT;
}
/**
* 小滴课堂,愿景:让技术不再难学 https://xdclass.net
*
* @Description 风控级别抽象类
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
* @Version 1.0
**/
public abstract class RiskControlManager {
protected String name;
/**
* 更严格的风控策略
*/
protected RiskControlManager superior;
public RiskControlManager(String name){
this.name = name;
}
/**
* 设置更严格的风控策略
* @param superior
*/
public void setSuperior(RiskControlManager superior){
this.superior = superior;
}
/**
* 处理请求
* @param request
*/
public abstract void handlerRequest(Request request);
}
/**
* 小滴课堂,愿景:让技术不再难学 https://xdclass.net
*
* @Description 风控级别抽象类
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
* @Version 1.0
**/
public class FirstRiskControlManager extends RiskControlManager {
public FirstRiskControlManager(String name) {
super(name);
}
/**
* 1000元以内可以直接处理
* @param request
*/
@Override
public void handlerRequest(Request request) {
if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()<=1000){
System.out.println("普通操作,输入支付密码即可");
System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");
}else {
//下个节点进行处理
if(superior!=null){
superior.handlerRequest(request);
}
}
}
}
public class SecondRiskControlManager extends RiskControlManager {
public SecondRiskControlManager(String name) {
super(name);
}
/**
* 处理 1千到1万之间
* @param request
*/
@Override
public void handlerRequest(Request request) {
if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()>1000 && request.getMoney()<10000){
System.out.println("稍大额操作,输入支付密码+短信验证码即可");
System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");
}else {
//下个节点进行处理
if(superior!=null){
superior.handlerRequest(request);
}
}
}
}
public class ThirdRiskControlManager extends RiskControlManager {
public ThirdRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(Request request) {
if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()>10000){
System.out.println("大额操作,输入支付密码+验证码+人脸识别 ");
System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");
}else {
//下个节点进行处理
if(superior!=null){
superior.handlerRequest(request);
}
}
}
}
//使用
public static void main(String[] args) {
RiskControlManager firstControlManager = new FirstRiskControlManager("初级风控");
RiskControlManager secondControlManager = new SecondRiskControlManager("中级风控");
RiskControlManager thirdControlManager = new ThirdRiskControlManager("高级风控");
//形成调用链
firstControlManager.setSuperior(secondControlManager);
secondControlManager.setSuperior(thirdControlManager);
//使用
Request request1 = new Request();
request1.setRequestType(RequestType.CASH_OUT.name());
request1.setMoney(20000);
firstControlManager.handlerRequest(request1);
}
-
优点
- 客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者 降低了耦合度
- 通过改变链内的调动它们的次序,允许动态地新增或者删除处理类,比较很方便维护
- 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则
- 每个类只需要处理自己该处理的工作,明确各类的责任范围,满足单一职责原则
-
缺点
- 处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象
- 不能保证请求一定被接收;
- 如果链路比较长,系统性能将受到一定影响,而且在进行代码调试时不太方便
-
日志处理级别
- dubug->info->warning->error
第3集 Command Pattern命令设计模式介绍和应用场景
简介:命令设计模式介绍和应用场景
-
命令设计模式(Command Pattern)
- 请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的对象,并把该命令传给相应的对象 执行命令,属于行为型模式
- 命令模式是一种特殊的策略模式,体现的是多个策略执行的问题,而不是选择的问题
-
应用场景
-
只要是你认为是命令的地方,就可以采用命令模式
-
日常每个界面、按钮、键盘 事件操作都是 命令设计模式
-
-
角色
- 抽象命令(Command):需要执行的所有命令都在这里声明
- 具体命令(ConcreteCommand):定义一个接收者和行为之间的弱耦合,实现execute()方法,负责调用接收者的相应操作,execute()方法通常叫做执行方法。
- 接受者(Receiver):负责具体实施和执行一个请求,干活的角色,命令传递到这里是应该被执行的,实施和执行请求的方法叫做行动方法
-
请求者(Invoker):负责调用命令对象执行请求,相关的方法叫做行动方法
-
客户端(Client):创建一个具体命令(ConcreteCommand)对象并确定其接收者。
//接受者,命令执行者
public class Receiver {
public void doSomething() {
System.out.println("Receiver---doSomething");
}
}
//抽象命令
public interface Command {
/**
* 执行动作
*/
void execute();
}
//具体命令
public class ConcreteCommand implements Command {
/**
* 对哪个receiver类进行命令处理
*/
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
/**
* 必须实现一个命令
*/
@Override
public void execute() {
System.out.println("ConcreteCommand---execute");
receiver.doSomething();
}
}
//请求者
public class Invoker {
private Command command;
public Invoker(Command command){
this.command = command;
}
/**
* 执行命令
*/
public void action(){
this.command.execute();
}
}
//使用
public static void main(String[] args) {
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
//创建请求者,把命令对象设置进去
Invoker invoker = new Invoker(command);
//执行方法
invoker.action();
}
第4集 命令设计模式之智能家居控制案例实战
简介:命令设计模式案例实战
- 业务需求
小滴课堂老王-搬新家了,他想实现智能家居,开发一个app,可以控制家里的家电,比如控制空调的开关、加热、制冷 等功能
利用命令设计模式,帮老王完成这个需求,注意:动作请求者就是手机app, 动作的执行者是家电的不同功能
- 编码
/**
* 小滴课堂,愿景:让技术不再难学 https://xdclass.net
*
* @Description 命令执行者
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
* @Version 1.0
**/
public class ConditionReceiver {
public void on(){
System.out.println("空调开启了");
}
public void off(){
System.out.println("空调关闭了");
}
public void cool(){
System.out.println("空调开始制冷");
}
public void warm(){
System.out.println("空调开始制暖");
}
}
public interface Command {
/**
* 执行动作
*/
void execute();
}
/**
* 小滴课堂,愿景:让技术不再难学 https://xdclass.net
*
* @Description 具体命令
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
* @Version 1.0
**/
public class OnCommand implements Command{
/**
* 对哪个receiver 进行命令处理
*/
private ConditionReceiver receiver;
public OnCommand(ConditionReceiver receiver){
this.receiver = receiver;
}
/**
* 必须实现一个命令的调用
*/
@Override
public void execute() {
System.out.println("OnCommand -> execute");
receiver.on();
}
}
public class OffCommand implements Command{
/**
* 对哪个receiver 进行命令处理
*/
private ConditionReceiver receiver;
public OffCommand(ConditionReceiver receiver){
this.receiver = receiver;
}
/**
* 必须实现一个命令的调用
*/
@Override
public void execute() {
System.out.println("OffCommand -> execute");
receiver.off();
}
}
public class CoolCommand implements Command{
/**
* 对哪个receiver 进行命令处理
*/
private ConditionReceiver receiver;
public CoolCommand(ConditionReceiver receiver){
this.receiver = receiver;
}
/**
* 必须实现一个命令的调用
*/
@Override
public void execute() {
System.out.println("CoolCommand -> execute");
receiver.cool();
}
}
/**
* 小滴课堂,愿景:让技术不再难学 https://xdclass.net
*
* @Description 请求者
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
* @Version 1.0
**/
public class AppInvoker {
private Command onCommand;
private Command offCommand;
private Command coolCommand;
private Command warmCommand;
public void setOnCommand(Command onCommand) {
this.onCommand = onCommand;
}
public void setOffCommand(Command offCommand) {
this.offCommand = offCommand;
}
public void setCoolCommand(Command coolCommand) {
this.coolCommand = coolCommand;
}
public void setWarmCommand(Command warmCommand) {
this.warmCommand = warmCommand;
}
/**
* 开机
*/
public void on(){
onCommand.execute();
}
/**
* 关机
*/
public void off(){
offCommand.execute();
}
public void warm(){
warmCommand.execute();
}
public void cool(){
coolCommand.execute();
}
}
//使用
public static void main(String[] args) {
//创建接受者,空调就是接受者
ConditionReceiver receiver = new ConditionReceiver();
//创建命令对象,设置命令的接受者
Command onCommand = new OnCommand(receiver);
Command offCommand = new OffCommand(receiver);
Command coolCommand = new CoolCommand(receiver);
Command warmCommand = new WarmCommand(receiver);
//创建请求者,把命令对象设置进去,app就是请求发起者
AppInvoker appInvoker = new AppInvoker();
appInvoker.setOnCommand(onCommand);
appInvoker.setOffCommand(offCommand);
appInvoker.setCoolCommand(coolCommand);
appInvoker.setWarmCommand(warmCommand);
appInvoker.on();
System.out.println();
appInvoker.cool();
System.out.println();
appInvoker.warm();
System.out.println();
appInvoker.off();
}
-
优点
- 调用者角色与接收者角色之间没有任何依赖关系,不需要了解到底是哪个接收者执行,降低了系统耦合度
- 扩展性强,新的命令可以很容易添加到系统中去。
-
缺点
- 过多的命令模式会导致某些系统有过多的具体命令类
第5集 IteratorPattern迭代器设计模式介绍和应用场景
简介:迭代器设计模式介绍和应用场景
-
迭代器设计模式(Iterator Pattern)
- 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部实现,属于行为型模式
- 应该是java中应用最多的设计模式之一
提到迭代器,想到它是与集合相关的,集合也叫容器,可以将集合看成是一个可以包容对象的容器,例如List,Set,Map,甚至数组都可以叫做集合,迭代器的作用就是把容器中的对象一个一个地遍历出来
-
应用场景
- 一般来说,迭代器模式是与集合是共存的,只要实现一个集合,就需要同时提供这个集合的迭代器,就像java中的Collection,List、Set、Map等 都有自己的迭代器
- JAVA 中的 iterator迭代器
-
角色
- 抽象容器(Aggregate):提供创建具体迭代器角色的接口,一般是接口,包括一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
- 具体容器角色(ConcreteAggregate):实现抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkedList, Set接口的哈希列表的实现HashSet等。
- 抽象迭代器角色(Iterator):负责定义访问和遍历元素的接口,包括几个核心方法,取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移除当前对象的方法remove()
- 具体迭代器角色(ConcreteIterator):实现迭代器接口中定义的方法,并要记录遍历中的当前位置,完成集合的迭代
第6集 迭代器模式案例实战之自定义List集合容器
简介:迭代器设计模式案例实战
- 案例需求
自定义一个集合容器,并实现里面的迭代器功能,List集合容器的简化版本
- 编码实战
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description 抽象迭代器
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
public interface Iterator {
/**
* 获取下个元素
* @return
*/
Object next();
/**
* 是否有下一个
* @return
*/
boolean hasNext();
/**
* 删除元素
* @param obj
* @return
*/
Object remove(Object obj);
}
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description 具体的迭代器
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
public class ConcreteIterator implements Iterator {
private List list;
private int index = 0;
public ConcreteIterator(List list){
this.list = list;
}
@Override
public Object next() {
Object obj = null;
if(this.hasNext()){
obj = this.list.get(index);
index++;
}
return obj;
}
@Override
public boolean hasNext() {
if(index == list.size()){
return false;
}
return true;
}
@Override
public Object remove(Object obj) {
return list.remove(obj);
}
}
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description 抽象容器建立了
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
public interface ICollection {
void add(Object obj);
void remove(Object obj);
Iterator iterator();
}
/**
* 小滴课堂,愿景:让技术不再难学
*
* @Description 容器简化版
* @Author 二当家小D
* @Remark 有问题直接联系我,源码-笔记-技术交流群
* @Version 1.0
**/
public class MyCollection implements ICollection {
private List list = new ArrayList();
@Override
public void add(Object obj) {
list.add(obj);
}
@Override
public void remove(Object obj) {
list.remove(obj);
}
@Override
public Iterator iterator() {
return new ConcreteIterator(list);
}
}
//使用
public static void main(String[] args) {
ICollection collection = new MyCollection();
collection.add("小滴课堂老王");
collection.add("小滴课堂Anna小姐姐");
collection.add("小滴课堂二当家小D");
collection.add("小滴课堂刘一手");
collection.add("小滴课堂老帆");
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
-
优点
-
可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据
-
支持以不同的方式遍历一个聚合对象
-
-
缺点
- 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐
- 迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常
- JDK源码 ArrayList的迭代器例子