龙空技术网

《架构成长篇四》java高阶必备,系统设计中设计模式的使用心得

软件架构成长之路 61

前言:

目前你们对“java课程设计心得体会范文”都比较着重,咱们都需要了解一些“java课程设计心得体会范文”的相关知识。那么小编在网摘上收集了一些关于“java课程设计心得体会范文””的相关知识,希望大家能喜欢,小伙伴们一起来了解一下吧!

前言

笔者会不定时的发布一些自己总结的经验,学习的成果(纯手打,原创)。如果觉得有用的话就关注分享点赞一下吧,笔者也会随着知识的增长对老文章进行修改,欢迎收藏一波。大家的支持也是我坚持下去的动力......

策略模式

策略模式应该是使用得最多的模式,用来替代一些不定时增长或修改的if-else(例如一个定时执行的任务,产品那边可能随时修改对应时间的执行策略,这时使用if-else会和策略产生耦合,使用策略模式替换能做到解耦,根据产品需求进行动态的配置)。

常用的策略模式结合spring的方式有两种:

第一种(通过上下文获取):Collection<Interface> values = applicationContext.getBeansOfType(Interface.class).values();Map<String,Interface> maps = new HashMap();values.for{ maps.put(value.getType(),value); applicationContext.getBeansOfType(Interface.class).values();}第二种(通过set注入):private Map<String,Interface> maps; public void setValues(Collection<Interface> values) { values.for{ maps.put(value.getType(),value); applicationContext.getBeansOfType(Interface.class).values(); }}依此可以拿到接口的所有实现类,在接口中可以定义一个返回type函数,子类实现这个函数(定义一个type值),放入type和实体的map中,然后策略根据这个type从其他动态配置项中获取需要实际执行的策略实现类。
观察者模式

观察者模式也就是发布-订阅模式,平常使用的mq,都是基于这种模式来设计的。使用的好处自然也和mq的作用一样,能做到生产者和观察者的解耦。一般我们系统业务中使用观察者模式主要用于统一事件处理,事件分发集中处理等场景;业务流程比较复杂的可以使用mq做事件转发到各个子系统处理(单个系统使用mq会导致复杂度太高,没必要还是尽量不用)。

单个系统中处理可以使用spring上下文的发布订阅来实现,Application.publishEvent (ApplicationEvent event)发送事件,定义实现ApplicationEvent的具体事件,代码如下:

public class CdEvent extends ApplicationEvent{  public CdEvent(Object source) { super(source); System.out.println("初始化 CdEvent"); } }

然后在对应的地方publishEvent即可。接收者需要实现ApplicationListener<Event>,泛型中是具体的实现类(即实现ApplicationEvent的具体事件),然后写具体实现业务即可,代码如下:

public class EventReceiver implements ApplicationListener<CdEvent>{  public void onApplicationEvent(CdEvent event) { System.out.println("监听到的事件:"+event.getSource()); }}
责任链模式

责任链模式比较适用于一些内部流程处理的业务,比如常见的过滤器,拦截器,netty的ChannelPipeline等。我们平常自己的系统业务也可以使用责任链,比如一个业务整个流程很长,但是其实可以拆分成很多个步骤,而且流程之间可能会进行前后处理调换的,那么就可以用责任链进行重构。

第一种(通过上下文获取):Collection<Interface> values = applicationContext.getBeansOfType(Interface.class).values();第二种(通过set注入):private Collection<Interface> values; public void setValues(Collection<Interface> values) { this.values = values; }获取到处理链的所有处理实现类后,怎么判断链条之间的前后关系呢?有两种方式,一种是在每个节点设置父节点是谁,这样父节点空的就是头节点,依次排列处理(不推荐);第二种是设置节点之间的排序关系,设置取出的列表中是按列表排序的集合,这样遍历处理即可,那如何保证每个实现类取出时是按顺序的呢?spring中可以用@Order标签配置每个实现类的权重,spring会根据这个值来设置优先级来执行获取。这样取出之后的就是根据你的需求排序好的链条了。
模板模式

模板模式是我们编写一些基类时必须要用到的,模板方法其实就是对抽象方法的使用,简单理解就是父类中实现了这一类的骨架,然后由子类来完成枝枝叶叶。这些枝叶就是在父类中定义的抽象方法由子类做不同的实现,就属于模板方法的运用,实际上就是对于多态的理解;但要用好模板方法远没有这么轻易,需要结合自己的设计能力,对业务的抽象能力来进行具体运用实现。常见的模板方法有两种:1.父类定义抽象方法,由子类进行实现(子类必须实现)。2.父类定义简单的公共实现,由子类进行重写(钩子方法)。具体使用哪种方式得视业务而定。常见的jdbcTemplate,BaseExecutor都是模板模式的运用成果。

组合模式

模板模式主要使用到继承,子类继承父类后实现抽象或者重写钩子方法,来完善父类的骨架;使用继承能够让我们合理的定义一些基类,很大限度的进行代码的重用,很好的描绘出类与类之间的关系,但这种情况会有一些局限性;

因为java中只允许单继承,所以继承之后局限了子类的扩展性。如果子类还需要有其它基类的功能,就会处于一个很尴尬的局面。当然有些同学会说可以用接口(其实不行,接口中不能有一些具体的实现,也就是骨架中只有一块块骨头,没有了拼接,就不能称为骨架了);还有些同学会说是设计的问题,需要从设计开始进行重构(那会是个浩大的工程,而且进行基类的重新整合可能会推翻之前定义的所有结构,容易诱发很多埋藏在之前子类中事故)。

继承中还有一个比较不好的点就是:继承父类之后需要实现父类及其应该实现的不知道几代祖宗的所有抽象方法,虽说实现了也不影响我们具体的使用,但是列了一堆不用的方法还是影响代码美观。

这时就要引出组合模式了,其实组合模式,说白了就是对象的引用,在本来需要使用多中功能的位置用对象的组合来替代继承,来完成各个类的功能引用。

适配器模式

适配器模式的理念就是将已经实现的新功能添加到老的接口中,让老的接口的实现可以使用新的功能。如我们要针对原来定义的老接口,让它使用到后面定义的新类的功能时;就可以设计一个适配器类继承了原有的老接口,然后在适配器类中引用新的类,在老接口的方法中添加新类对象的功能即可,放张uml图吧:

代理模式,装饰者模式

代理模式,其实也是对象的引用(感觉绝大多数模式都是对象引用...)。例如适配器模式,也可以理解成异构的代理模式,适配器类也可以理解成为new-impl的代理,被代理以后可以在适配器中进行其他的操作,只不过适配器中方法来源是old-interface,而代理的方法来源是自己(继承或实现对应方法的接口)。

代理的主要作用在于可以隐藏具体的实现,在代理类的实现中可以对原来的方法进行增强。对于一些批量的类管理还可以用动态代理来实现,例如常见的springAOP,dubbo的服务发现。拿dubbo的服务发现来说,调用服务将暴露接口的服务生成动态代理类,在调用时动态增强一些容错方案(fast fail, failover等等)以及负载均衡等策略,同时隐藏了服务提供方的具体实现。

动态代理的实现方式有两种,一种时jdk动态代理,一种时cglib的动态代理。jdk代理的方式是基于接口来实现的,cglib是则不需要接口(基于继承实现)。

装饰者模式,其实和代理模式理念差不多,也是通过对象引用来对原来的实现进行装饰,但与代理模式不同的是,装饰者可能会对原有实现进行动态的装饰,代理于实现之间是一对一的关系,而装饰者与实现可能是多对一的关系。这就需要每个装饰者与实现之间类型匹配并且不会重复调用实现,放一张标准类图:

下面放个装饰者模式比较好的讲解链接:

标签: #java课程设计心得体会范文