当前位置: 首页 > news >正文

鞍山百度网站怎么制作亚马逊雨林图片

鞍山百度网站怎么制作,亚马逊雨林图片,深圳建网站价格,淘客网站怎么做百度单例模式 单例模式是指一个类在一个进程中只有一个实例对象#xff08;但也不一定#xff0c;比如Spring中的Bean的单例是指在一个容器中是单例的#xff09; 单例模式创建分为饿汉式和懒汉式#xff0c;总共大概有8种写法。但是在开源项目中使用最多的主要有两种写法但也不一定比如Spring中的Bean的单例是指在一个容器中是单例的 单例模式创建分为饿汉式和懒汉式总共大概有8种写法。但是在开源项目中使用最多的主要有两种写法 1、静态常量 静态常量方式属于饿汉式以静态变量的方式声明对象。这种单例模式在Spring中使用的比较多举个例子在Spring中对于Bean的名称生成有个类AnnotationBeanNameGenerator就是单例的。 AnnotationBeanNameGenerator 2、双重检查机制 除了上面一种还有一种双重检查机制在开源项目中也使用的比较多而且在面试中也比较喜欢问。双重检查机制方式属于懒汉式代码如下 public class Singleton {private volatile static Singleton INSTANCE;private Singleton() {}public static Singleton getInstance() {if (INSTANCE  null) {synchronized (Singleton.class) {if (INSTANCE  null) {INSTANCE  new Singleton();}}}return INSTANCE;}}之所以这种方式叫双重检查机制主要是在创建对象的时候进行了两次INSTANCE null的判断。 疑问讲解 这里解释一下双重检查机制的三个疑问 外层判断null的作用 内层判断null的作用 变量使用volatile关键字修饰的作用 外层判断null的作用其实就是为了减少进入同步代码块的次数提高效率。你想一下其实去了外层的判断其实是可以的但是每次获取对象都需要进入同步代码块实在是没有必要。 内层判断null的作用防止多次创建对象。假设AB同时走到同步代码块A先抢到锁进入代码创建了对象释放锁此时B进入代码块如果没有判断null那么就会直接再次创建对象那么就不是单例的了所以需要进行判断null防止重复创建单例对象。 volatile关键字的作用防止重排序。因为创建对象的过程不是原子大概会分为三个步骤 第一步分配内存空间给Singleton这个对象 第二步初始化对象 第三步将INSTANCE变量指向Singleton这个对象内存地址 假设没有使用volatile关键字发生了重排序第二步和第三步执行过程被调换了也就是先将INSTANCE变量指向Singleton这个对象内存地址再初始化对象。这样在发生并发的情况下另一个线程经过第一个if非空判断时发现已经为不为空就直接返回了这个对象但是此时这个对象还未初始化内部的属性可能都是空值一旦被使用的话就很有可能出现空指针这些问题。 双重检查机制在dubbo中的应用 在dubbo的spi机制中获取对象的时候有这样一段代码 虽然这段代码跟上面的单例的写法有点不同但是不难看出其实是使用了双重检查机制来创建对象保证对象单例。 建造者模式 将一个复杂对象的构造与它的表示分离使同样的构建过程可以创建不同的表示这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象然后一步一步构建而成。 上面的意思看起来很绕其实在实际开发中其实建造者模式使用的还是比较多的比如有时在创建一个pojo对象时就可以使用建造者模式来创建 PersonDTO personDTO  PersonDTO.builder().name(三友的java日记).age(18).sex(1).phone(188****9527).build();上面这段代码就是通过建造者模式构建了一个PersonDTO对象所以建造者模式又被称为Budiler模式。 这种模式在创建对象的时候看起来比较优雅当构造参数比较多的时候适合使用建造者模式。 接下来就来看看建造者模式在开源项目中是如何运用的 1、在Spring中的运用 我们都知道Spring在创建Bean之前会将每个Bean的声明封装成对应的一个BeanDefinition而BeanDefinition会封装很多属性所以Spring为了更加优雅地创建BeanDefinition就提供了BeanDefinitionBuilder这个建造者类。 BeanDefinitionBuilder 2、在Guava中的运用 在项目中如果我们需要使用本地缓存会使用本地缓存的实现的框架来创建一个比如在使用Guava来创建本地缓存时就会这么写 CacheString, String cache  CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.MINUTES).maximumSize(200).build();这其实也就是建造者模式。 建造者模式不仅在开源项目中有所使用在JDK源码中也有使用到比如StringBuilder类。 最后上面说的建造者模式其实算是在Java中一种简化的方式如果想了解一下传统的建造者模式可以看一下这篇文章 https://m.runoob.com/design-pattern/builder-pattern.html?ivk_sa1024320u 工厂模式 工厂模式在开源项目中也使用的非常多具体的实现大概可以细分为三种 简单工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 简单工厂模式就跟名字一样的确很简单。比如说现在有个动物接口Animal具体的实现有猫Cat、狗Dog等等而每个具体的动物对象创建过程很复杂有各种各样地步骤此时就可以使用简单工厂来封装对象的创建过程调用者不需要关心对象是如何具体创建的。 public class SimpleAnimalFactory {public Animal createAnimal(String animalType) {if (cat.equals(animalType)) {Cat cat  new Cat();//一系列复杂操作return cat;} else if (dog.equals(animalType)) {Dog dog  new Dog();//一系列复杂操作return dog;} else {throw new RuntimeException(animalType  animalType  无法创建对应对象);}}}当需要使用这些对象调用者就可以直接通过简单工厂创建就行。 SimpleAnimalFactory animalFactory  new SimpleAnimalFactory(); Animal cat  animalFactory.createAnimal(cat);需要注意的是一般来说如果每个动物对象的创建只需要简单地new一下就行了那么其实就无需使用工厂模式工厂模式适合对象创建过程复杂的场景。 工厂方法模式 上面说的简单工厂模式看起来没啥问题但是还是违反了七大设计原则的OCP原则也就是开闭原则。所谓的开闭原则就是对修改关闭对扩展开放。 什么叫对修改关闭就是尽可能不修改的意思。就拿上面的例子来说如果现在新增了一种动物兔子那么createAnimal方法就得修改增加一种类型的判断那么就此时就出现了修改代码的行为也就违反了对修改关闭的原则。 所以解决简单工厂模式违反开闭原则的问题就可以使用工厂方法模式来解决。 /*** 工厂接口*/ public interface AnimalFactory {Animal createAnimal(); }/*** 小猫实现*/ public class CatFactory implements AnimalFactory {Overridepublic Animal createAnimal() {Cat cat  new Cat();//一系列复杂操作return cat;} }/*** 小狗实现*/ public class DogFactory implements AnimalFactory {Overridepublic Animal createAnimal() {Dog dog  new Dog();//一系列复杂操作return dog;} }这种方式就是工厂方法模式。他将动物工厂提取成一个接口AnimalFactory具体每个动物都各自实现这个接口每种动物都有各自的创建工厂如果调用者需要创建动物就可以通过各自的工厂来实现。 AnimalFactory animalFactory  new CatFactory(); Animal cat  animalFactory.createAnimal();此时假设需要新增一个动物兔子那么只需要实现AnimalFactory接口就行对于原来的猫和狗的实现其实代码是不需要修改的遵守了对修改关闭的原则同时由于是对扩展开放实现接口就是扩展的意思那么也就符合扩展开放的原则。 抽象工厂模式 工厂方法模式其实是创建一个产品的工厂比如上面的例子中AnimalFactory其实只创建动物这一个产品。而抽象工厂模式特点就是创建一系列产品比如说不同的动物吃的东西是不一样的那么就可以加入食物这个产品通过抽象工厂模式来实现。 public interface AnimalFactory {Animal createAnimal();Food createFood();}在动物工厂中新增了创建食物的接口小狗小猫的工厂去实现这个接口创建狗粮和猫粮这里就不去写了。 1、工厂模式在Mybatis的运用 在Mybatis中当需要调用Mapper接口执行sql的时候需要先获取到SqlSession通过SqlSession再获取到Mapper接口的动态代理对象而SqlSession的构造过程比较复杂所以就提供了SqlSessionFactory工厂类来封装SqlSession的创建过程。 SqlSessionFactory及默认实现DefaultSqlSessionFactory 对于使用者来说只需要通过SqlSessionFactory来获取到SqlSession而无需关心SqlSession是如何创建的。 2、工厂模式在Spring中的运用 我们知道Spring中的Bean是通过BeanFactory创建的。 BeanFactory就是Bean生成的工厂。一个Spring Bean在生成过程中会经历复杂的一个生命周期而这些生命周期对于使用者来说是无需关心的所以就可以将Bean创建过程的逻辑给封装起来提取出一个Bean的工厂。 策略模式 策略模式也比较常见就比如说在Spring源码中就有很多地方都使用到了策略模式。 在讲策略模式是什么之前先来举个例子这个例子我在之前的《写出漂亮代码的45个小技巧》文章提到过。 假设现在有一个需求需要将消息推送到不同的平台。 最简单的做法其实就是使用if else来做判断就行了。 public void notifyMessage(User user, String content, int notifyType) {if (notifyType  0) {//调用短信通知的api发送短信} else if (notifyType  1) {//调用app通知的api发送消息} }根据不同的平台类型进行判断调用对应的api发送消息。 虽然这样能实现功能但是跟上面的提到的简单工厂的问题是一样的同样违反了开闭原则。当需要增加一种平台类型比如邮件通知那么就得修改notifyMessage的方法再次进行else if的判断然后调用发送邮件的邮件发送消息。 此时就可以使用策略模式来优化了。 首先设计一个策略接口 public interface MessageNotifier {/*** 是否支持改类型的通知的方式** param notifyType 0:短信 1:app* return*/boolean support(int notifyType);/*** 通知** param user* param content*/void notify(User user, String content);}短信通知实现 Component public class SMSMessageNotifier implements MessageNotifier {Overridepublic boolean support(int notifyType) {return notifyType  0;}Overridepublic void notify(User user, String content) {//调用短信通知的api发送短信} }app通知实现 public class AppMessageNotifier implements MessageNotifier {Overridepublic boolean support(int notifyType) {return notifyType  1;}Overridepublic void notify(User user, String content) {//调用通知app通知的api} }最后notifyMessage的实现只需要要循环调用所有的MessageNotifier的support方法一旦support方法返回true说明当前MessageNotifier支持该类的消息发送最后再调用notify发送消息就可以了。 Resource private ListMessageNotifier messageNotifiers;public void notifyMessage(User user, String content, int notifyType) {for (MessageNotifier messageNotifier : messageNotifiers) {if (messageNotifier.support(notifyType)) {messageNotifier.notify(user, content);}} }那么如果现在需要支持通过邮件通知只需要实现MessageNotifier接口注入到Spring容器就行其余的代码根本不需要有任何变动。 到这其实可以更好的理解策略模式了。就拿上面举的例子来说短信通知app通知等其实都是发送消息一种策略而策略模式就是需要将这些策略进行封装抽取共性使这些策略之间相互替换。 策略模式在SpringMVC中的运用 1、对接口方法参数的处理 比如说我们经常在写接口的时候会使用到了PathVariable、RequestParam、RequestBody等注解一旦我们使用了注解SpringMVC会处理注解从请求中获取到参数然后再调用接口传递过来而这个过程就使用到了策略模式。 对于这类参数的解析SpringMVC提供了一个策略接口HandlerMethodArgumentResolver HandlerMethodArgumentResolver 这个接口的定义就跟我们上面定义的差不多不同的参数处理只需要实现这个解决就行比如上面提到的几个注解都有对应的实现。 比如处理RequestParam注解的RequestParamMethodArgumentResolver的实现。 RequestParamMethodArgumentResolver 当然还有其它很多的实现如果想知道各种注解处理的过程只需要找到对应的实现类就行了。 2、对接口返回值的处理 同样SpringMVC对于返回值的处理也是基于策略模式来实现的。 HandlerMethodReturnValueHandler HandlerMethodReturnValueHandler接口定义跟上面都是同一种套路。 比如说常见的对于ResponseBody注解处理的实现RequestResponseBodyMethodProcessor。 ResponseBody注解处理的实现RequestResponseBodyMethodProcessor 同样HandlerMethodReturnValueHandler的实现也有很多这里就不再举例了。 策略模式在Spring的运用远不止这两处就比如我在《三万字盘点Spring/Boot的那些常用扩展点》文章提到过对于配置文件的加载PropertySourceLoader也是策略模式的运用。 模板方法模式 模板方法模式是指在父类中定义一个操作中的框架而操作步骤的具体实现交由子类做。其核心思想就是对于功能实现的顺序步骤是一定的但是具体每一步如何实现交由子类决定。 比如说对于旅游来说一般有以下几个步骤 做攻略选择目的地 收拾行李 乘坐交通工具去目的地 玩耍、拍照 乘坐交通工具去返回 但是对于去哪收拾什么东西都乘坐什么交通工具都是由具体某个旅行来决定。 那么对于旅游这个过程使用模板方法模式翻译成代码如下 public abstract class Travel {public void travel() {//做攻略makePlan();//收拾行李packUp();//去目的地toDestination();//玩耍、拍照play();//乘坐交通工具去返回backHome();}protected abstract void makePlan();protected abstract void packUp();protected abstract void toDestination();protected abstract void play();protected abstract void backHome();}对于某次旅行来说只需要重写每个步骤该做的事就行比如说这次可以选择去杭州西湖下次可以去长城但是对于旅行过程来说是不变了对于调用者来说只需要调用暴露的travel方法就行。 可能这说的还是比较抽象我再举两个模板方法模式在源码中实现的例子。 模板方法模式在源码中的使用 1、模板方法模式在HashMap中的使用 HashMap我们都很熟悉可以通过put方法存元素并且在元素添加成功之后会调用一下afterNodeInsertion方法。 而afterNodeInsertion其实是在HashMap中是空实现什么事都没干。 afterNodeInsertion 这其实就是模板方法模式。HashMap定义了一个流程那就是当元素成功添加之后会调用afterNodeInsertion子类如果需要在元素添加之后做什么事那么重写afterNodeInsertion就行。 正巧JDK中的LinkedHashMap重写了这个方法。 而这段代码主要干的一件事就是可能会移除最老的元素至于到底会不会移除得看if是否成立。 添加元素移除最老的元素基于这种特性其实可以实现LRU算法比如Mybatis的LruCache就是基于LinkedHashMap实现的有兴趣的可以扒扒源码这里就不再展开讲了。 2、模板方法模式在Spring中的运用 我们都知道在Spring中ApplicationContext在使用之前需要调用一下refresh方法而refresh方法就定义了整个容器刷新的执行流程代码。 refresh方法部分截图 在整个刷新过程有一个onRefresh方法 onRefresh方法 而onRefresh方法默认是没有做任何事并且在注释上有清楚两个单词Template method翻译过来就是模板方法的意思所以onRefresh就是一个模板方法并且方法内部的注释也表明了这个方法是为了子类提供的。 在Web环境下子类会重写这个方法然后创建一个Web服务器。 3、模板方法模式在Mybatis中的使用 在Mybatis中是使用Executor执行Sql的。 Executor 而Mybatis一级缓存就在Executor的抽象实现中BaseExecutor实现的。如图所示红圈就是一级缓存 BaseExecutor 比如在查询的时候如果一级缓存有那么就处理缓存的数据没有的话就调用queryFromDatabase从数据库查 queryFromDatabase会调用doQuery方法从数据库查数据然后放入一级缓存中。 而doQuery是个抽象方法 所以doQuery其实就是一个模板方法需要子类真正实现从数据库中查询数据所以这里就使用了模板方法模式。 责任链模式 在责任链模式里很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递由该链上的某一个对象或者某几个对象决定处理此请求每个对象在整个处理过程中值扮演一个小小的角色。 举个例子现在有个请假的审批流程根据请假的人的级别审批到的领导不同比如有有组长、主管、HR、分管经理等等。 先需要定义一个处理抽象类抽象类有个下一个处理对象的引用提供了抽象处理方法还有一个对下一个处理对象的调用方法。 public abstract class ApprovalHandler {/*** 责任链中的下一个处理对象*/protected ApprovalHandler next;/*** 设置下一个处理对象** param approvalHandler*/public void nextHandler(ApprovalHandler approvalHandler) {this.next  approvalHandler;}/*** 处理** param approvalContext*/public abstract void approval(ApprovalContext approvalContext);/*** 调用下一个处理对象** param approvalContext*/protected void invokeNext(ApprovalContext approvalContext) {if (next ! null) {next.approval(approvalContext);}}}几种审批人的实现 //组长审批实现 public class GroupLeaderApprovalHandler extends ApprovalHandler {Overridepublic void approval(ApprovalContext approvalContext) {System.out.println(组长审批);//调用下一个处理对象进行处理invokeNext(approvalContext);} }//主管审批实现 public class DirectorApprovalHandler extends ApprovalHandler {Overridepublic void approval(ApprovalContext approvalContext) {System.out.println(主管审批);//调用下一个处理对象进行处理invokeNext(approvalContext);} }//hr审批实现 public class HrApprovalHandler extends ApprovalHandler {Overridepublic void approval(ApprovalContext approvalContext) {System.out.println(hr审批);//调用下一个处理对象进行处理invokeNext(approvalContext);} }有了这几个实现之后接下来就需要对对象进行组装组成一个链条比如在Spring中就可以这么玩。 Component public class ApprovalHandlerChain {Autowiredprivate GroupLeaderApprovalHandler groupLeaderApprovalHandler;Autowiredprivate DirectorApprovalHandler directorApprovalHandler;Autowiredprivate HrApprovalHandler hrApprovalHandler;public ApprovalHandler getChain() {//组长处理完下一个处理对象是主管groupLeaderApprovalHandler.nextHandler(directorApprovalHandler);//主管处理完下一个处理对象是hrdirectorApprovalHandler.nextHandler(hrApprovalHandler);//返回组长这样就从组长开始审批一条链就完成了return groupLeaderApprovalHandler;}}之后对于调用方而言只需要获取到链条开始处理就行。 一旦后面出现需要增加或者减少审批人只需要调整链条中的节点就行对于调用者来说是无感知的。 责任链模式在开源项目中的使用 1、在SpringMVC中的使用 在SpringMVC中可以通过使用HandlerInterceptor对每个请求进行拦截。 HandlerInterceptor 而HandlerInterceptor其实就使用到了责任链模式但是这种责任链模式的写法跟上面举的例子写法不太一样。 对于HandlerInterceptor的调用是在HandlerExecutionChain中完成的。 HandlerExecutionChain 比如说对于请求处理前的拦截就在是这样调用的。 其实就是循环遍历每个HandlerInterceptor调用preHandle方法。 2、在Sentinel中的使用 Sentinel是阿里开源的一个流量治理组件而Sentinel核心逻辑的执行其实就是一条责任链。 在Sentinel中有个核心抽象类AbstractLinkedProcessorSlot AbstractLinkedProcessorSlot 这个组件内部也维护了下一个节点对象这个类扮演的角色跟例子中的ApprovalHandler类是一样的写法也比较相似。这个组件有很多实现 比如有比较核心的几个实现 DegradeSlot熔断降级的实现 FlowSlot流量控制的实现 StatisticSlot统计的实现比如统计请求成功的次数、异常次数为限流提供数据来源 SystemSlot根据系统规则来进行流量控制 整个链条的组装的实现是由DefaultSlotChainBuilder实现的 DefaultSlotChainBuilder 并且内部是使用了SPI机制来加载每个处理节点 所以如果你想自定一些处理逻辑就可以基于SPI机制来扩展。 除了上面的例子比如Gateway网关、Dubbo、MyBatis等等框架中都有责任链模式的身影所以责任链模式使用的还是比较多的。 代理模式 代理模式也是开源项目中很常见的使用的一种设计模式这种模式可以在不改变原有代码的情况下增加功能。 举个例子比如现在有个PersonService接口和它的实现类PersonServiceImpl //接口 public interface PersonService {void savePerson(PersonDTO person);}//实现 public class PersonServiceImpl implements PersonService{Overridepublic void savePerson(PersonDTO person) {//保存人员信息} }这个类刚开始运行的好好的但是突然之前不知道咋回事了有报错需要追寻入参所以此时就可以这么写。 public class PersonServiceImpl implements PersonService {Overridepublic void savePerson(PersonDTO person) {log.info(savePerson接口入参:{}, JSON.toJSONString(person));//保存人员信息} }这么写就修改了代码万一以后不需要打印日志了呢岂不是又要修改代码不符和之前说的开闭原则那么怎么写呢可以这么玩。 public class PersonServiceProxy implements PersonService {private final PersonService personService  new PersonServiceImpl();Overridepublic void savePerson(PersonDTO person) {log.info(savePerson接口入参:{}, JSON.toJSONString(person));personService.savePerson(person);} }可以实现一个代理类PersonServiceProxy对PersonServiceImpl进行代理这个代理类干的事就是打印日志最后调用PersonServiceImpl进行人员信息的保存这就是代理模式。 当需要打印日志就使用PersonServiceProxy不需要打印日志就使用PersonServiceImpl这样就行了不需要改原有代码的实现。 讲到了代理模式就不得不提一下Spring AOPSpring AOP其实跟静态代理很像最终其实也是调用目标对象的方法只不过是动态生成的这里就不展开讲解了。 代理模式在Mybtais中的使用 前面在说模板方法模式的时候举了一个BaseExecutor使用到了模板方法模式的例子并且在BaseExecutor这里面还完成了一级缓存的操作。 其实不光是一级缓存是通过Executor实现的二级缓存其实也是只不过不在BaseExecutor里面实现而是在CachingExecutor中实现的。 CachingExecutor CachingExecutor中内部有一个Executor类型的属性delegatedelegate单词的意思就是代理的意思所以CachingExecutor显然就是一个代理类这里就使用到了代理模式。 CachingExecutor的实现原理其实很简单先从二级缓存查查不到就通过被代理的对象查找数据而被代理的Executor在Mybatis中默认使用的是SimpleExecutor实现SimpleExecutor继承自BaseExecutor。 这里思考一下二级缓存为什么不像一级缓存一样直接写到BaseExecutor中 这里我猜测一下是为了减少耦合。 我们知道Mybatis的一级缓存默认是开启的一级缓存写在BaseExecutor中的话那么只要是继承了BaseExecutor就拥有了一级缓存的能力。 但二级缓存默认是不开启的如果写在BaseExecutor中讲道理也是可以的但不符和单一职责的原则类的功能过多同时会耦合很多判断代码比如开启二级缓存走什么逻辑不开启二级缓存走什么逻辑。而使用代理模式很好的解决了这一问题只需要在创建的Executor的时候判断是否开启二级缓存开启的话就用CachingExecutor代理一下不开启的话老老实实返回未被代理的对象就行默认是SimpleExecutor。 如图所示是构建Executor对象的源码一旦开启了二级缓存就会将前面创建的Executor进行代理构建一个CachingExecutor返回。 适配器模式 适配器模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作将一个类的接口转换成客户希望的另一个接口。 举个生活中的例子比如手机充电器接口类型有USB TypeC接口和Micro USB接口等。现在需要给一个Micro USB接口的手机充电但是现在只有USB TypeC接口的充电器这怎么办呢 其实一般可以弄个一个USB TypeC转Micro USB接口的转接头这样就可以给Micro USB接口手机充电了代码如下 USBTypeC接口充电 public class USBTypeC {public void chargeTypeC() {System.out.println(开启充电了);}}MicroUSB接口 public interface MicroUSB {void charge();}适配实现最后是调用USBTypeC接口来充电 public class MicroUSBAdapter implements MicroUSB {private final USBTypeC usbTypeC  new USBTypeC();Overridepublic void charge() {//使用usb来充电usbTypeC.chargeTypeC();}}方然除了上面这种写法还有一种继承的写法。 public class MicroUSBAdapter extends USBTypeC implements MicroUSB {Overridepublic void charge() {//使用usb来充电this.chargeTypeC();}}这两种写法主要是继承和组合聚合的区别。 这样就可以通过适配器转接头就可以实现USBTypeC给MicroUSB接口充电。 适配器模式在日志中的使用 在日常开发中日志是必不可少的可以帮助我们快速快速定位问题但是日志框架比较多比如Slf4j、Log4j等等一般同一系统都使用一种日志框架。 但是像Mybatis这种框架来说它本身在运行的过程中也需要产生日志但是Mybatis框架在设计的时候无法知道项目中具体使用的是什么日志框架所以只能适配各种日志框架项目中使用什么框架Mybatis就使用什么框架。 为此Mybatis提供一个Log接口 而不同的日志框架只需要适配这个接口就可以了 Slf4jLoggerImpl 就拿Slf4j的实现来看内部依赖了一个Slf4j框架中的Logger对象最后所有日志的打印都是通过Slf4j框架中的Logger对象来实现的。 此外Mybatis还提供了如下的一些实现 这样Mybatis在需要打印日志的时候只需要从Mybatis自己的LogFactory中获取到Log对象就行至于最终获取到的是什么Log实现由最终项目中使用日志框架来决定。 观察者模式 当对象间存在一对多关系时则使用观察者模式Observer Pattern。比如当一个对象被修改时则会自动通知依赖它的对象。 这是什么意思呢举个例子来说假设发生了火灾可能需要打119、救人那么就可以基于观察者模式来实现打119、救人的操作只需要观察火灾的发生一旦发生就触发相应的逻辑。 观察者的核心优点就是观察者和被观察者是解耦合的。就拿上面的例子来说火灾事件被观察者根本不关系有几个监听器观察者当以后需要有变动只需要扩展监听器就行对于事件的发布者和其它监听器是无需做任何改变的。 观察者模式实现起来比较复杂这里我举一下Spring事件的例子来说明一下。 观察者模式在Spring事件中的运用 Spring事件就是Spring基于观察者模式实现的一套API如果有不知道不知道Spring事件的小伙伴可以看看《三万字盘点Spring/Boot的那些常用扩展点》这篇文章里面有对Spring事件的详细介绍这里就不对使用进行介绍了。 Spring事件的实现比较简单其实就是当Bean在生成完成之后会将所有的ApplicationListener接口实现监听器添加到ApplicationEventMulticaster中。 ApplicationEventMulticaster可以理解为一个调度中心的作用可以将事件通知给监听器触发监听器的执行。 ApplicationEventMulticaster可以理解为一个总线 retrieverCache中存储了事件类型和对应监听器的缓存。当发布事件的时候会通过事件的类型找到对应的监听器然后循环调用监听器。 所以Spring的观察者模式实现的其实也不复杂。 总结 本文通过对设计模式的讲解加源码举例的方式介绍了9种在代码设计中常用的设计模式 单例模式 建造者模式 工厂模式 策略模式 模板方法模式 责任链模式 代理模式 适配器模式 观察者模式 其实这些设计模式不仅在源码中常见在平时工作中也是可以经常使用到的。 设计模式其实还是一种思想或者是套路性的东西至于设计模式具体怎么用、如何用、代码如何写还得依靠具体的场景来进行灵活的判断。
http://www.zqtcl.cn/news/803939/

相关文章:

  • 手机微网站开发的目的和意义温州公司网站开发
  • 除了外链 还有什么办法使网站提高排名网站建设珠海 新盈科技
  • 几分钟弄清楚php做网站中国风景摄影网
  • 卡片式网站网页设计公司的市场评估
  • 网站开发的感想wordpress水煮鱼
  • 网站开发入门培训机构自豪地采用wordpress更改
  • 手机网站来几个最近的国际新闻大事件
  • 重庆网站开发设计公司电话资源网站优化排名
  • 国土分局网站建设方案外贸seo网站
  • 营销型网站建设易网拓烟台h5网站建设公司
  • PHP网站开发都需要学什么中介网站模板
  • 网站建设与维护模板官方网站建设费用应入什么科目
  • 网站建设企业关键词seo关键词库
  • 美容院网站源码wordpress scandir
  • 长春电商网站建设报价北京创意设计协会网站
  • 企业3合1网站建设公司加强政协网站建设
  • 专业做互联网招聘的网站有哪些内容百度搜索引擎推广收费标准
  • 物流网站开发系统论文怎么知道网站程序是什么做的
  • 湖南高端网站制作公php网站后台
  • 建好的网站在哪里wordpress部署到git
  • 浙江坤宇建设有限公司网站毕业设计 旅游网站建设
  • 做网站月收入多少视频短视频api
  • 泰安网站建设哪家强网站流量指标
  • 网站毕业设计开题报告wordpress账户密码忘记
  • 做网站学费多少钱0基础学app程序开发
  • 忻州建站公司辽宁省建设执业信息网官网
  • 北京网站建设 云智互联集安网站建设
  • 无锡市建设培训中心网站私人订制软件平台
  • 宁波网站设计推荐荣盛网络招远网站制作
  • 网站开发维护运维室内设计师怎么找