郑州网站建设msgg,功能多的免费网站建设,淘客做网站多少钱,如何开公司一. 责任链模式1. 背景在现实生活中#xff0c;常常会出现这样的事例#xff1a;一个请求有多个对象可以处理#xff0c;但每个对象的处理条件或权限不同。例如#xff0c;公司员工请假#xff0c;可批假的领导有部门负责人、副总经理、总经理等#xff0c;但每个领导能批…一. 责任链模式1. 背景 在现实生活中常常会出现这样的事例一个请求有多个对象可以处理但每个对象的处理条件或权限不同。例如公司员工请假可批假的领导有部门负责人、副总经理、总经理等但每个领导能批准的天数不同员工必须根据自己要请假的天数去找不同的领导签名也就是说员工必须记住每个领导的姓名、电话和地址等信息这增加了难度。这样的例子还有很多如找领导出差报销、生活中的“击鼓传花”游戏等。2. 定义和特点(1). 定义为了避免请求发送者与多个请求处理者耦合在一起将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链当有请求发生时可将请求沿着这条链传递直到有对象处理它为止。PS责任链模式也叫职责链模式。在责任链模式中客户只需要将请求发送到责任链上即可无须关心请求的处理细节和请求的传递过程所以责任链将请求的发送者和请求的处理者解耦了。(2). 优点 A. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构发送者和接收者也无须拥有对方的明确信息。 B. 增强了系统的可扩展性。可以根据需要增加新的请求处理类满足开闭原则。 C. 增强了给对象指派职责的灵活性。当工作流程发生变化可以动态地改变链内的成员或者调动它们的次序也可动态地新增或者删除责任。 D. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用不需保持其他所有处理者的引用这避免了使用众多的 if 或者 if···else 语句。 E. 责任分担。每个类只需要处理自己该处理的工作不该处理的传递给下一个对象完成明确各类的责任范围符合类的单一职责原则。(3). 缺点 A. 不能保证每个请求一定被处理。由于一个请求没有明确的接收者所以不能保证它一定会被处理该请求可能一直传到链的末端都得不到处理。 B. 对比较长的职责链请求的处理可能涉及多个处理对象系统性能将受到一定影响。 C. 职责链建立的合理性要靠客户端来保证增加了客户端的复杂性可能会由于职责链的错误设置而导致系统出错如可能会造成循环调用。3. 具体实现(1). 模式结构 A. 抽象处理者定义一个处理请求的接口包含抽象处理方法和一个后继连接。 B. 具体处理者实现抽象处理者的处理方法判断能否处理本次请求如果可以处理请求则处理否则将该请求转给它的后继者。 C. 客户端调用创建处理链并向链头的具体处理者对象提交请求它不关心处理细节和请求的传递过程。结构图如下(2). 使用场景 员工请假不同的天数需要被不同级别的领导批准这个时候可以采用责任链模式。每个领导都是一个具体的请假处理者同时提炼出来一个抽象处理者包括请假处理方法和下一个节点最后由客户端建立责任链并将请求传递进去。更多C后台开发技术点知识内容包括C/CLinuxNginxZeroMQMySQLRedisMongoDBZK流媒体音视频开发Linux内核TCP/IP协程DPDK多个高级知识点。C/CLinux服务器开发高级架构师/C后台开发架构师免费学习地址【文章福利】另外还整理一些C后台开发架构师 相关学习资料面试题教学视频以及学习路线图免费分享有需要的可以点击领取(3). 代码实操请假请求类 /// summary/// 请假请求类/// /summarypublic class LeaveRequest{/// summary/// 姓名/// /summarypublic string name { get; set; }/// summary/// 请假天数/// /summarypublic int leaveDays { get; set; }}抽象处理者和具体处理者 /// summary/// 抽象处理者角色/// /summarypublic abstract class AbstractHandler{/// summary/// 代表责任链中的下一个角色/// /summarypublic AbstractHandler NextHandler { get; set; }/// summary/// 处理请假请求/// /summarypublic abstract void HandleRequest(LeaveRequest request);}/// summary/// 直接领导(一级领导)/// /summarypublic class LeaderHandler1 : AbstractHandler{/// summary/// 处理请假请求/// /summarypublic override void HandleRequest(LeaveRequest request){if (request.leaveDays3){Console.WriteLine($直接领导(一级领导)已经批准{request.name}的请假请求,请假天数{request.leaveDays});}else{if (this.NextHandler!null){this.NextHandler.HandleRequest(request);}else{Console.WriteLine(${request.name}请假天数太多没有人批准该假条);}}}}/// summary/// 二级领导/// /summarypublic class LeaderHandler2 : AbstractHandler{/// summary/// 处理请假请求/// /summarypublic override void HandleRequest(LeaveRequest request){if (request.leaveDays 3 request.leaveDays 7){Console.WriteLine($二级领导已经批准{request.name}的请假请求,请假天数{request.leaveDays});}else{if (this.NextHandler ! null){this.NextHandler.HandleRequest(request);}else{Console.WriteLine(${request.name}请假天数太多没有人批准该假条);}}}}/// summary/// 最高领导(三级)/// /summarypublic class LeaderHandler3 : AbstractHandler{/// summary/// 处理请假请求/// /summarypublic override void HandleRequest(LeaveRequest request){if (request.leaveDays 7 request.leaveDays 30){Console.WriteLine($最高领导(三级)已经批准{request.name}的请假请求,请假天数{request.leaveDays});}else{if (this.NextHandler ! null){this.NextHandler.HandleRequest(request);}else{Console.WriteLine(${request.name}请假天数太多没有人批准该假条);}}}}
客户单创建责任链并调用 //1. 有人要请假LeaveRequest myRequest1 new LeaveRequest() { name小明,leaveDays6};LeaveRequest myRequest2 new LeaveRequest(){name 小王,leaveDays 2};LeaveRequest myRequest3 new LeaveRequest(){name 小放,leaveDays 15};LeaveRequest myRequest4 new LeaveRequest(){name 张三,leaveDays 35};//2. 请假相关的责任链LeaderHandler1 handler1 new LeaderHandler1();LeaderHandler2 handler2 new LeaderHandler2();LeaderHandler3 handler3 new LeaderHandler3();handler1.NextHandler handler2;handler2.NextHandler handler3;//3.进行请假处理handler1.HandleRequest(myRequest1);handler1.HandleRequest(myRequest2);handler1.HandleRequest(myRequest3);handler1.HandleRequest(myRequest4);测试结果4. 适用场景分析 (1). 有多个对象可以处理一个请求哪个对象处理该请求由运行时刻自动确定。 (2). 可动态指定一组对象处理请求或添加新的处理者。 (3). 在不明确指定请求处理者的情况下向多个处理者中的一个提交请求。二. 迭代器模式1. 背景 在现实生活以及程序设计中经常要访问一个聚合对象中的各个元素如【数据结构】中的链表遍历通常的做法是将链表的创建和遍历都放在同一个类中但这种方式不利于程序的扩展如果要更换遍历方法就必须修改程序源代码这违背了 “开闭原则”。既然将遍历方法封装在聚合类中不可取那么聚合类中不提供遍历方法将遍历方法由用户自己实现是否可行呢答案是同样不可取因为这种方式会存在两个缺点 A. 暴露了聚合类的内部表示使其数据不安全 B. 增加了客户的负担。 “迭代器模式”能较好地克服以上缺点它在客户访问类与聚合类之间插入一个迭代器这分离了聚合对象与其遍历行为对客户也隐藏了其内部细节且满足“单一职责原则”和“开闭原则”。比如C#中的List就实现了迭代器模式。2. 定义和特点(1). 定义提供一个对象来顺序访问聚合对象中的一系列数据而不暴露聚合对象的内部表示。(2). 优点 A. 访问一个聚合对象的内容而无须暴露它的内部表示。 B. 遍历任务交由迭代器完成这简化了聚合类。 C. 它支持以不同方式遍历一个聚合甚至可以自定义迭代器的子类以支持新的遍历。 D. 增加新的聚合类和迭代器类都很方便无须修改原有代码。 E. 封装性良好为遍历不同的聚合结构提供一个统一的接口。(3). 缺点 增加了类的个数这在一定程度上增加了系统的复杂性3. 具体实现(1). 模式结构 迭代器模式是通过将聚合对象的遍历行为分离出来抽象成迭代器类来实现的其目的是在不暴露聚合对象的内部结构的情况下让外部代码透明地访问聚合的内部数据。 A. 抽象聚合Aggregate角色定义存储、添加、删除聚合对象以及创建迭代器对象的接口。 B. 具体聚合ConcreteAggregate角色实现抽象聚合类返回一个具体迭代器的实例。 C. 抽象迭代器Iterator角色定义访问和遍历聚合元素的接口通常包含 hasNext()、first()、next() 等方法。 D. 具体迭代器Concretelterator角色实现抽象迭代器接口中所定义的方法完成对聚合对象的遍历记录遍历的当前位置。结构如下图(2). 使用场景 见下面代码模拟。(3). 代码实操聚合接口和具体的聚合类 /// summary/// 抽象聚合接口/// /summarypublic interface IAggregateT{public void Add(T obj);public void Remove(T obj);/// summary/// 获取聚合对象的迭代器/// /summary/// returns/returnspublic IteratorT GetIterator();}/// summary/// 具体聚合/// /summarypublic class ConcreteAggregateT : IAggregateT{private ListT list new ListT();public void Add(T obj){list.Add(obj);}public void Remove(T obj){list.Remove(obj);}/// summary/// 获取迭代器/// /summary/// returns/returnspublic IteratorT GetIterator(){return new ConcreteIteratorT(list);}}抽象迭代器和具体的迭代器 /// summary/// 抽象迭代器/// /summarypublic interface IteratorT{T First();T Next();bool HasNext();}/// summary/// 具体的迭代器/// /summary/// typeparam nameT/typeparampublic class ConcreteIteratorT : IteratorT{private ListT list null;private int index 0;public ConcreteIterator(ListT myList){this.list myList;}public T First(){return list[0];}public bool HasNext(){if (indexlist.Count-1){return true;}else{return false;}}public T Next(){T obj default(T);if (this.HasNext()){obj list[index];}return obj;}}测试{//聚合对象添加数据IAggregatestring ag new ConcreteAggregatestring();ag.Add(001);ag.Add(002);ag.Add(003);ag.Add(004);//获取对应的迭代器Iteratorstring it ag.GetIterator();//输出数据Console.WriteLine($第一个元素为:{it.First()});Console.WriteLine(剩下的元素为);while (it.HasNext()){Console.WriteLine(it.Next());}
}运行结果4. 适用场景分析 (1). 当需要为聚合对象提供多种遍历方式时。 (2). 当需要为遍历不同的聚合结构提供一个统一的接口时。 (3). 当访问一个聚合对象的内容而无须暴露其内部细节的表示时。PS: 由于聚合与迭代器的关系非常密切所以大多数语言在实现聚合类时都提供了迭代器类因此大数情况下使用语言中已有的聚合类的迭代器就已经够了。原文链接https://www.cnblogs.com/yaopengfei/p/13489597.html