重学设计模式pdf下载

核心提示作者:小傅哥博客:https://bugstack.cn沉淀、分享、成长,让自己和他人都能有所收获!目录一、前言二、开发环境三、组合模式介绍四、案例场景模拟五、用一坨坨代码实现1. 工程结构2. 代码实现3. 测试验证六、组合模式重构代码1

作者:https://bugstack.cn付晓兄弟博客

沉淀,分享,成长,让自己和他人都有所收获!

目录

1.前言2。开发环境3。组合模式4介绍。案例情景模拟5。用代码块1实现。工程结构2。代码实现3。测试验证6。组合模式1的重构代码。工程结构2。代码实现3。测试验证7。总结。

一.导言

只有孩子做选择题,大人做。

刚开始几年,只要群里问我该学哪种开发语言,哪种语言最好。我肯定群里的聊天特别火。有人支持PHP,有人调用Java,也有C++和C#。然而近年来,人们似乎真的没有剑、枪、棍、斧、钩、叉了。大多数时候,他们都在开玩笑,大吵大闹。同时,在互联网的整体发展中,一些开发语言在很多情况下是通用的,从而共同打造整体生态圈。而人们选择的方式也更倾向于选择不同领域适合的架构,而不是一味的追求某一种语言。这可以给很多编程新手一些建议。不要刻意去认为某一种语言是好的,某一种语言是坏的,在合适的场景下选择最需要的就可以了。想选择的语言可以参考招聘网站的需求和薪资水平来确定。

编程不是表演。

总会有人喜欢在整个项目开发中使用一些新特性,尝试他们的新知识。这样说不好。甚至可以说,这是一部分热爱学习、创新、实践的人。但是,除了使用新特性,编程还需要考虑整体的可扩展性、可读性、可维护性、易扩展等方面。就像你家雇了一群装修工,有一个苦力喜欢卖弄技术,喜欢做花。他在家里的淋浴下面装了一个马桶。

即使写CRUD也应该有一个设计模式。

很多时候很多大需求都是通过增删查堆出来的。今天,我们需要一个需求,如果明天,我们将添加一个内容来扩展它。积累的需求会越来越大,扩容和维护的成本会越来越高。往往大部分RD没有产品思维和整体业务需求导向,总认为写好代码完成功能就够了。但这样不考虑扩展性的实现,很难让后续需求快速迭代,久而久之就会陷入恶性循环,每天都有bug要改。

第二,发展环境

JDK 1.8Idea+Maven涉及三个项目,关注“微信官方账号”即可获取:bugstack虫洞栈,回复源代码下载。

三。组合模式介绍

组合图案,图片来自refactoringguru.cn。从上图可以看出,有点像螺丝螺母,通过一堆链接组织成结构树。将相似的对象组合成一组可调用的结构树对象的设计思想称为复合模式。

这种设计允许您的服务组节点自由组合并向外界提供服务。例如,您有三个原子验证功能服务,并提供外部调用。有的调用者需要用AB组合,有的调用者需要用CBA组合,有的可能只用三者之一。此时,您可以使用复合模式来构建服务,并为不同类型的调用方配置不同的组织关系树。您可以将这种树形结构配置到数据库中,或者通过图形界面连续控制树形结构。

因此,在适当的利益场景下使用不同的设计模式,可以使代码逻辑非常清晰,易于扩展,同时也可以降低新团队成员的学习成本。

四。案例情景模拟

场景模式;上面的营销决策树是营销规则决策树的一个非常简化的版本。根据性别和年龄发放不同类型的优惠券,刺激消费,达到用户精准推广的目的。

虽然有些小伙伴可能没有开发营销场景,但你可能一直在被营销。比如你经常浏览机械键盘、笔记本电脑、汽车装饰等。那种男人喜欢,并且长期给你推荐这样的优惠券,刺激你消费。然后如果你购物不多,或者钱不在自己手里。你坐过汽车吗?有一段时间,你的小伙伴经常喊,为什么同样的距离,他在10元,我在15元?其实这些都是营销的案例。一般不经常使用软件的小伙伴,经常会出一点力来推广自己的活动,增加用户粘性。

所以这里我们模拟一个类似的决策场景,可见组合模式的重要性。此外,组合模式不仅可以应用于规则决策树,还可以作为服务包装器组合配置不同的接口,提供对外服务能力,降低开发成本。

第五,用成堆的代码实现。

下面以ifelse的诞生为例,介绍一下小姐姐和程序员之间的故事引发的意外。

1.工程结构

it-stack-demo-design-8-01 └-src └-main └-java └-org.itstack . demo . design EngineController.java公司如果都有这样的程序员,└-It肯定会节省很多成本,根本不用建微服务。一但是不要那样做!酒过肠,佛留心中。世人若学我,如入魔道。2.代码实现

public classenginecontroller { private Logger Logger = Logger factory . get Logger;公共字符串进程{ logger.infoif){ if {返回“水果A”;}if {return“果b”;} }if) {if {return“果C”;}if {return“果d”;} } returnnull}}}除了扩展性和维护性,这段代码实现起来是最快的。而且从外观上看,也非常适合新人理解。但是我劝你不要写。编写这样的代码将会导致绩效降低或解雇。3.测试验证

3.1编写测试类

@ testpublicvidtest _ engine controller { engine controller engine controller = new engine controller;string process = engine controller . process;logger.info}这里我们模拟一个用户ID,传输性别:男,年龄:29。我们的预期结果是:水果b .实际业务是给光头程序员发枸杞券。3.2测试结果

22:10:12.891[main]info o . I . demo . design . Engine Controller-if else判断用户结果的实现方式。userid:oli 09 plkdjh usersex:man userage:2922:10:12.898[main]info org . it stack . demo . design . test . API test-test结果:fruit BProcess结束,退出代码为0从测试结果可以看出,我们的程序运行正常,符合预期,但我们不建议实现。接下来,我们将通过使用组合模式来优化这部分代码。第六,组合模式重构代码

接下来,通过使用复合模式来优化代码是一个小的重构。

下一个重构部分的代码改动会比较大,这样我们就可以把不同类型的决策节点和最终的果实组装成一棵可以运行的决策树。我们需要做自适应设计和工厂方法调用,具体会体现在定义接口、抽象类和初始化配置决策节点。这部分代码建议多看几遍,最好练习一下。

1.工程结构

it stack-demo-design-8-02│──src│╸──main│┖┖──Java│┖──org . it stack . demo . design . domain│├──Model│││├──aggregates││┖┖┖──TreeRich.java│┖┖──VO│┖╸──EngineResult.java│╸──TreeNode.java││^╻

组合模式模型结构可以先看黑框的模拟引导树结构;1,11,12,111,112,121,122,是一组树形结构的id,节点串联起来形成关系树。接下来,类图部分,在左边,自适应决策过滤器是从LogicFilter定义的。baseLogic是接口的实现,提供了最基本的通用方法。UserAgeFilter和UserGenerFilter是判断年龄和性别的两个具体实现类。最后,是引擎来执行这个可以组织的决策树。此外,还定义了引擎接口和基础的配置,并在配置中设置了所需的模式决策节点。接下来,将详细解释每个类。如果你觉得没看过,那一定是我作者表达的不够清楚。可以加我微信和我交流。2.代码实现

2.1基本目标

2.2树节点的逻辑过滤界面。

public interface logic filter {Long filter;String matter value;}该部分定义了自适应、逻辑决策器和获取决策值的通用接口,使得每个提供决策能力的节点都必须实现该接口,以保证统一性。2.3决策抽象类提供基本服务。

publicatabstractclassbaselogiimplementslogicfilter { @ override public Long filter { for { if } return nodeline . getnodeidto;} return0L} @ Overridepublicabstract String matter value;privatebooleandeisionlogic { switch){ case 1:return matter value . equals);case2:返回double . parse double > double . parse double);case3:返回double . parse double < double . parse double);case4:返回double . parse double = double . parse double);默认值:returnfalse}}}实现了抽象方法中的接口方法,同时定义了基本的决策方法;1,2,3,4,5,等于,小于,大于,小于等于,大于等于。同时定义了抽象方法,使得每个实现接口的类都必须根据规则提供一个决策值,这个决策值用于逻辑比较。2.4树节点逻辑实现类

“年龄节点”

public class useragefilterextendsbasellogic { @ override public String matter value { return decision matter . get;}} "性别节点"

public class user genderfilterextendsbasellogic { @ override public String matter value { return decision matter . get;}}}以上两个决策逻辑的节点都可以用很简单的方式获取值,获取用户的参数即可。实际业务开发可以从数据库、RPC接口、缓存操作等途径获得。2.5决策引擎接口的定义

public interfaceiengine { engine result process;}对于用户来说,还需要定义一个统一的界面操作。这个优点非常方便后期开发不同类型的决策引擎,即可以构建不同的决策工厂。2.6决策节点配置

public classengineconfig { static Map logicFilterMap;static { logicFilterMap = new concurrent hashmap;logicfiltermap . put);logicfiltermap . put);}公共地图getLogicFilterMap { return logicFilterMap;} publicvidsetlogicfiltermap { this . logicFilterMap = logicFilterMap;}}这里把可以提供服务的决策节点配置成map结构,这样的map结构可以提取到数据库中,所以管理起来非常方便。2.7基本决策引擎功能

publicacstractclasseinginebaseextendsgineconfigimplementsiengine { private Logger Logger = Logger factory . get Logger;@ Overridepublicabstract engine result process;受保护的TreeNode engine decision maker { tree root tree root = tree rich . gettree root;map treeNodeMap = tree rich . gettreenodemap;//规则根id longrootnodeid = tree root . gettreerootnodeid;TreeNode TreeNode info = TreeNode map . get;//节点类型[nodetype];1子叶,2果。equals){ string rule key = treenode info . getrulekey;logic filter logic filter = logicfiltermap . get;string matter value = logic filter . matter value;long next node = logic filter . filter);treenode info = treenode map . get;logger.info,userId,treeId,treeNodeInfo.getTreeNodeId,ruleKey,matter value);}返回treeNodeInfo}}这里主要提供决策树流的处理过程,有点像通过链接在二叉树中寻找水果节点的过程。同时,它为外部实现提供了执行决策过程的抽象方法。2.8决策引擎的实现

publiclasstreenginehandleextendsenginebase { @ override public engine result process {//决策过程treenode = engineecionmaker//决策结果返回新的引擎结果,treenode . getnodevalue);}}这里的决策引擎实现很简单,通过传入必要的信息;决策树信息,决定材料值,做出具体的树形结构决策。3.测试验证

3.1装配树关系

@ beforepublicvodinit {//node:1 tree node _ 01 = new tree node;treeNode _ 01.setTreeIdtreeNode _ 01.setTreeNodeIdtreeNode _ 01.setNodeTypetreeNode _ 01.setNodevaluetreeNode _ 01.setRuleKeytreeNode _ 01.setRuleDesc//link:1-> 11 treenode link treenode link _ 11 = new treenode link;treeNodelink _ 11.setNodeIdFromtreeNodelink _ 11.setNodeIdTotreenode link _ 11 . setrulelimittype;treenode link _ 11 . setrulelimitvalue;//link:1-> 12 treenode link treenode link _ 12 = newtreenode link;treeNodelink _ 12.setNodeIdTotreeNodelink _ 12.setNodeIdTotreenode link _ 12 . setrulelimittype;treenode link _ 12 . setrulelimitvalue;list treenode linklist _ 1 = new ArrayList;treeNodelinkList _ 1.addtreeNodelinkList _ 1.addtreeNode _ 01 . settreenodelinklist;//node:11 treenode _ 11 = new treenode;treeNode _ 11.setTreeIdtreeNode _ 11.setTreeNodeIdtreeNode _ 11.setNodeTypetreeNode _ 11.setNodevaluetreeNode _ 11.setRuleKeytreeNode _ 11.setRuleDesc//link:11-> 111 treenode link treenode link _ 111 = newtreenode link;treenode link _ 111 . setnodeidfrom;treeNodelink _ 111.setNodeIdTotreenode link _ 111 . setrulelimittype;treenode link _ 111 . setrulelimitvalue;//link:11-> 112 treenode link treenode link _ 112 = newtreenode link;treenode link _ 112 . setnodeidfrom;treeNodelink _ 112.setNodeIdTotreenode link _ 112 . setrulelimittype;treenode link _ 112 . setrulelimitvalue;List treeNodelinkList_11 =新的ArrayListtreenode linklist _ 11 . add;treenode linklist _ 11 . add;treeNode _ 11 . settreenodelinklist;//node:12 tree node _ 12 = new tree node;treeNode _ 12.setTreeIdtreeNode _ 12.setTreeNodeIdtreeNode _ 12.setNodeTypetreeNode _ 12.setNodevaluetreeNode _ 12.setRuleKeytreeNode _ 12.setRuleDesc//link:12-> 121 treenode link treenode link _ 121 = newtreenode link;treenode link _ 121 . setnodeidfrom;treeNodelink _ 121.setNodeIdTotreenode link _ 121 . setrulelimittype;treenode link _ 121 . setrulelimitvalue;//link:12-> 122 treenode link treenode link _ 122 = newtreenode link;treenode link _ 122 . setnodeidfrom;treeNodelink _ 122.setNodeIdTotreenode link _ 122 . setrulelimittype;treenode link _ 122 . setrulelimitvalue;List treeNodelinkList_12 =新的ArrayListtreenode linklist _ 12 . add;treenode linklist _ 12 . add;treeNode _ 12 . settreenodelinklist;//node:111 treenode _ 111 = new treenode;treeNode _ 111.setTreeIdtreeNode _ 111.setTreeNodeIdtreeNode _ 111.setNodeTypetreeNode _ 111.setNodevalue//node:112 tree node _ 112 = new tree node;treeNode _ 112.setTreeIdtreeNode _ 112.setTreeNodeIdtreeNode _ 112.setNodeTypetreeNode _ 112.setNodevalue//node:121 tree node _ 121 = new tree node;treeNode _ 121.setTreeIdtreeNode _ 121.setTreeNodeIdtreeNode _ 121.setNodeTypetreeNode _ 121.setNodevalue//node:122 tree node _ 122 = new tree node;treeNode _ 122.setTreeIdtreeNode _ 122.setTreeNodeIdtreeNode _ 122.setNodeTypetreeNode _ 122.setNodevalue//tree root tree root = new tree root;treeRoot.setTreeIdtreeRoot.setTreeRootNodeIdtreeRoot.setTreeNameMap treeNodeMap = new HashMaptreeNodeMap.puttreeNodeMap.puttreeNodeMap.puttreeNodeMap.puttreeNodeMap.puttreeNodeMap.puttreeNodeMap.puttreeRich = new TreeRich}

树形结构的组织关系是“重要的”,这部分是组合模式非常重要的运用。在建立的决策树关系下,我们可以创建树的每个节点,并使用链接将节点串联起来。到时候,如果需要做什么业务扩展,可以在里面添加相应的节点,进行动态配置。这种手动组合方式可以提取到数据库中,因此可以扩展到图形界面进行配置操作。3.2编写测试类

@ testpublicvidtest _ tree { logger . info);ie engine treengine handle = new treengine handle;Map decisionMatter = new HashMapdecisionMatter.putdecisionMatter.putengine result result = treenginehandle . process;logger . info);}这里提供组织模式创建的流程决策树,调用时传入决策树的ID。如果是业务开发,决策树和业务的绑定关系很容易解耦,可以根据需要传入决策树ID。此外,我们还提供待处理的信息;男性,年龄,参数信息。3.3测试结果

23:35:05.711[main]o . I . d . d . service . engine . engine base-决策树engine = >规则决策树userid: oli09plkdjh树id: 10001 treenode: 11 rulekey:用户性别重要值:man 23:35:05.712[MA in]o . I . d . d . d . service . engine . engine base-决策树engine = >规则决策树userid: oli09plkdjh树id: 100但目前在这种和的组合模式设计下,后续的扩展和修改非常方便。已经建立了整体组织关系框架和呼叫决策流程。如果看完这个还没有完全理解,可以下载代码观察结构,运行调试。七。摘要

从上面的决策树场景来看,复合模式的主要解决方案是,在不同结构的组织下,一系列简单的逻辑节点或扩展的复杂逻辑节点对于外部调用仍然可以非常简单。这部分设计模式保证了开闭原则,你可以提供新的逻辑节点的使用,组织新的关系树,而不需要改变模型结构。但是如果把一些功能差异很大的接口打包,会变得更加困难,但也不是不能处理好,只是需要一些适配和具体的开发。很多时候,因为你的极致追求和一点固执的工匠精神,即使面对同样的业务需求,你也能完成最好的代码结构和最具扩展性的技术架构。不要因为不能被引导提高能力而影响放弃追求!

虫洞堆栈

沉淀,分享,成长,让自己和他人都有所收获!

作者肖福哥,从事一线互联网Java开发多年。从19年开始,他整理了一份工作和学习过程的技术总结,旨在为你提供一份清晰详细的核心技能学习文档。如果这篇文章能帮到你,请给予支持!

 
友情链接
鄂ICP备19019357号-22