日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
【分享】我在阿里工作十年里接觸過的Java框架設(shè)計(jì)模式

 一、前言

說起來設(shè)計(jì)模式,大家應(yīng)該都耳熟能詳,設(shè)計(jì)模式代表了軟件設(shè)計(jì)的最佳實(shí)踐,是經(jīng)過不斷總結(jié)提煉出來的代碼設(shè)計(jì)經(jīng)驗(yàn)的分類總結(jié),這些模式或者可以簡化代碼,或者可以是代碼邏輯開起來清晰,或者對功能擴(kuò)展很方便…

設(shè)計(jì)模式按照使用場景可以分為三大類:創(chuàng)建型模式(Creational Patterns)、結(jié)構(gòu)型模式(Structural Patterns)、行為型模式(Behavioral Patterns)。

  • 創(chuàng)建型模式(Creational Patterns)

    對對象的實(shí)例化過程進(jìn)行抽象,這使得一個系統(tǒng)可以不用關(guān)心這些對象是如何創(chuàng)建,組合,呈現(xiàn)的,對于類創(chuàng)建模式來說通過使用繼承改變實(shí)例化的類,對于對象創(chuàng)建模式來說通過使用代理來實(shí)例化所需要的對象。

  • 結(jié)構(gòu)型模式(Structural Patterns)

    通過對多個類和對象進(jìn)行組合得到復(fù)雜結(jié)構(gòu)的類,一般使用繼承繼承或者成員變量引用形式來實(shí)現(xiàn)。

  • 行為型模式(Behavioral Patterns)

    行為模式不僅表達(dá)了對象和類,還表達(dá)了他們之間的交互,涉及到了對象和算法的分配。

下面就帶大家看下開源框架框架中是如何應(yīng)用這些經(jīng)典設(shè)計(jì)模式的。

二、責(zé)任鏈設(shè)計(jì)模式(Chain of Responsibility Pattern)

2.1 介紹

責(zé)任鏈模式是把多個對象串聯(lián)起來形成一個鏈狀結(jié)構(gòu),讓每個對象都有機(jī)會對事件發(fā)送者的請求進(jìn)行處理。責(zé)任鏈模式是設(shè)計(jì)模式中的行為模式,設(shè)計(jì)意圖是為了使事件發(fā)送者和事件接受者之間解耦。通常責(zé)任鏈鏈中的每個對象都有下一個對象的引入(例如tomcat 里面StandardPipeline用來管理valve),或者有個同一個鏈管理工廠里面使用數(shù)組存放了所有的對象(例如tomcat里面ApplicationFilterChain用來關(guān)系filter)。

2.2 Tomcat中Valve鏈

Tomcat中StandardEngine,StandardHost,StandardContext里面都有自己StandardPipeline,下面以StandardEngine里面StandardPipeline為例講解

從上面類圖可知道每個Valve都要繼承ValveBase類,該類里面有一個Valve的引用,實(shí)際是鏈中下一個節(jié)點(diǎn)對象,Valve就是通過每個Valve里面的next串聯(lián)為鏈的。

每個valve的invoke方法里面調(diào)用next.invoke激活鏈中下一個節(jié)點(diǎn),并且StandardEngine,StandardHost,StandardContext都有一個basic valve這個valve在鏈的末尾用來激活子容器的valve鏈。

2.3 Tomcat中Filter鏈

Tomcat中Filter鏈?zhǔn)鞘褂肁pplicationFilterChain來管理的,具體結(jié)構(gòu)如下圖:

可知Filter鏈不是像Valve一樣在內(nèi)部維護(hù)下個節(jié)點(diǎn)的引用,而是在ApplicationFilterChain中搞了個數(shù)組存放所有的Filter,并通過n統(tǒng)計(jì)Filter總個數(shù),pos是當(dāng)前filter的下標(biāo)。

ApplicationFilterChain的doFilter代碼如下:

public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { ... internalDoFilter(request,response); ... }private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { //獲取filter鏈中下標(biāo)為pos的filter ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { filter = filterConfig.getFilter(); support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } ... //調(diào)用自定義filter的dofilter方法 filter.doFilter(request, response, this); support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } .... } .....}

2.4 使用場景

  • 當(dāng)一個請求需要根據(jù)請求參數(shù)的不同由不同對象來處理時候。

  • 當(dāng)一個請求需要固定對象順序處理,并且可擴(kuò)展性的在固定順序里面插入新的對象進(jìn)行處理時候。

三、工廠模式(Factory Pattern)

3.1 介紹

工廠模式是創(chuàng)建型模式,他封裝了對象的創(chuàng)建過程,調(diào)用者使用具體的工廠方法根據(jù)參數(shù)就可以獲取對應(yīng)的對象。

3.2 Spring框架中BeanFactory

如圖BeanFactory接口提供了getBean方法,在AbstractBeanFactory中實(shí)現(xiàn)了該方法,經(jīng)過層層繼承,實(shí)現(xiàn),最后DefaultListableBeanFactory實(shí)現(xiàn)了BeanDefinitionRegistry接口用來保存bean定義,繼承了AbstractAutowireCapableBeanFactory用來支撐autowired。

一個例子

@Testpublic void testBeanFactoy() throws NamingException, SQLException, ParseException, IOException { //創(chuàng)建Bean工廠 DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); //給bean工廠添加bean定義,解析xml里面的bean放入bean工廠 loadBeanDefinitions(bf); //根據(jù)名字從bean工廠獲取bean Hello hello = (Hello) bf.getBean("hello"); hello.sayHello(); Hello2 hello2 = (Hello2) bf.getBean("hello2"); hello2.sayHello();}protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); String[] configLocations = new String[] { "beans2.xml" }; if (configLocations != null) { beanDefinitionReader.loadBeanDefinitions(configLocations); }}

3.3 使用場景

  • 不同條件下創(chuàng)建不同實(shí)例,用于統(tǒng)一管理bean

  • 不同條件下調(diào)用不同工廠方法獲取不同場景下的bean

四、單例設(shè)計(jì)模式(Singleton Pattern)

4.1 介紹

單例模式是一種創(chuàng)建型模式,單例模式提供一個創(chuàng)建對象的接口,但是多次調(diào)用該接口返回的是同一個實(shí)例的引用,目的是為了保證只有一個實(shí)例,并且提供一個訪問這個實(shí)例的統(tǒng)一接口。

4.2 Spring中單例bean的創(chuàng)建

Spring中默認(rèn)配置的bean的scope為singleton,也就是單例作用域。那么看看它是如何做到的。

在AbstractBeanFactory類里面的doGetBean方法:

protected Object doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean = null; // 解決set循環(huán)依賴 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { ... } else { ... // 創(chuàng)建單件bean. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { ... throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //創(chuàng)建原型bean else if (mbd.isPrototype()) { ... } //創(chuàng)建request作用域bean else { ... } } ... return bean;}

getSingleton代碼:

public Object getSingleton(String beanName, ObjectFactory singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { ... beforeSingletonCreation(beanName); ... try { singletonObject = singletonFactory.getObject(); } catch (BeanCreationException ex) { ... } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); }}protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); }}private final Map singletonObjects = CollectionFactory.createConcurrentMapIfPossible(16);

可知Spring內(nèi)部是通過一個ConcurrentMap來管理單件bean的。獲取bean時候會先看看singletonObjects中是否有,有則直接返回,沒有則創(chuàng)建后放入。

看個時序圖:

Spring的bean工廠管理的單例模式管理的是多個bean實(shí)例的單例,是工廠模式管理所有的bean,而每個bean的創(chuàng)建又使用了單例模式。

4.4 使用場景

  • 同一個jvm應(yīng)用的不同模塊需要使用同一個對象實(shí)例進(jìn)行信息共享。

  • 需要同一個實(shí)例來生成全局統(tǒng)一的序列號。

五、原型設(shè)計(jì)模式(Prototype Pattern)

5.1 介紹

相比單例設(shè)計(jì)模式,原型模式是每次創(chuàng)建一個對象,下面看下spring是如何使用原型模式的。

5.2 Spring中原型bean的創(chuàng)建

創(chuàng)建原型bean需要在xml特別說明:

protected  T doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { ... } else { ... try { ... // Create bean instance. if (mbd.isSingleton()) { ... } //創(chuàng)建原型bean else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { ... } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } }... return (T) bean;}

createBean函數(shù)里面則是根據(jù)bean定義創(chuàng)建新bean,感興趣的可以看看。

5.3 使用場景

  • 當(dāng)有業(yè)務(wù)場景使用某個bean時候需要使用自己的一個拷貝的時候使用。

六、 策略模式(Strategy Pattern)

6.1 介紹

策略模式屬于行為性模式,它定義一系列的算法對象,使用時候可以使它們相互替換。

6.2 Spring中bean實(shí)例化策略

首先看下類圖:

從圖知道:接口InstantiationStrategy是實(shí)例化策略接口類,它定義了三個實(shí)例化接口,然后SimpleInstantiationStrategy實(shí)現(xiàn)了該策略,它主要做一些簡單的根據(jù)構(gòu)造函數(shù)實(shí)例號bean的工作,然后CglibSubclassingInstantiationStrategy又繼承了SimpleInstantiationStrategy新增了方法注入方式根據(jù)cglib生成代理類實(shí)例化方法。

在AbstractAutowireCapableBeanFactory中管理了該策略的一個對象,默認(rèn)是CglibSubclassingInstantiationStrategy策略,運(yùn)行時候可以通過setInstantiationStrategy改變實(shí)例化策略,如果你自己寫個策略的話。

6.3 Spring中Aop代理策略

首先看AopProxyFactory接口類提供了createAopProxy接口,這個是策略模式的接口方法。然后DefaultAopProxyFactory實(shí)現(xiàn)了該接口作為策略的實(shí)現(xiàn)者。然后ProxyCreatorSupport里面引用了AopProxyFactory,并且提供了get,set方法用來運(yùn)行時改變策略,這里Spring只實(shí)現(xiàn)了DefaultAopProxyFactory這一個策略,如果需要自己也可以寫個。

DefaultAopProxyFactory里面的createAopProxy的邏輯如下,可以在運(yùn)行時根據(jù)參數(shù)決定用Cglib策略還是JDK動態(tài)代理策略生成代理類:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //如果XML打開了優(yōu)化開關(guān),或者設(shè)置為了代理目標(biāo)類,或者目前類沒有接口 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } //如果有接口,或者通過Proxy.newProxyInstance生成的,則使用jdk動態(tài)代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //使用cglib return new ObjenesisCglibAopProxy(config); } else { //使用jdk動態(tài)代理 return new JdkDynamicAopProxy(config); } }

另外AopProxy也是一個策略接口類,具體實(shí)現(xiàn)的策略為JdkDynamicAopProxy,CglibAopProxy,ObjenesisCglibAopProxy。

6.4 Tomcat中Digester解析server.xml

tomcat中的Digester是為了解析server.xml的,其中每個元素都有一個解析規(guī)則就是Rule ,類圖如下:

DigestER一開始先指定不同的解析策略(Rule),然后在具體解析Server.xml時候根據(jù)節(jié)點(diǎn)不同使用不同解析策略來解析節(jié)點(diǎn)。

如圖在解析每個節(jié)點(diǎn)時候會先找到該節(jié)點(diǎn)對應(yīng)的解析策略,然后循環(huán)去調(diào)用所有解析策略的方法去處理。

6.5 使用場景

運(yùn)行時根據(jù)條件的不同使用不同的策略處理一個事情,與責(zé)任鏈不同在于,責(zé)任鏈?zhǔn)且粋€鏈條,一個事情可以被責(zé)任鏈里面所有節(jié)點(diǎn)處理,而策略模式則是只有有一個對象來處理。

七、 門面模式(Facade Pattern)

7.1 介紹

門面模式是一種結(jié)構(gòu)性模式,它通過新增一個門面類對外暴露系統(tǒng)提供的一部分功能,或者屏蔽了內(nèi)部系統(tǒng)的復(fù)雜性,對外部僅僅暴露一個簡單的接口,或者通過調(diào)用不同的服務(wù)對外提供統(tǒng)一的接口,讓使用者對這些內(nèi)部服務(wù)透明化。

7.2 模板引擎Velocity中門面模式使用

Velocity里面的VelocityEngine和Velocity類都是RuntimeInstance類的門面,后者提供了模板渲染的所有功能,前兩者則是內(nèi)部維護(hù)RuntimeInstance的實(shí)例,具體工作還是委托給RuntimeInstance來實(shí)現(xiàn)。

關(guān)于Veloctiy可以參考:https://www.atatech.org/articles/78435

如圖 RuntimeInstance提供了Velocity引擎的所用功能,VelocityEngine內(nèi)部直接引用了RuntimeInstance的一個實(shí)例,VelocityEngine對外暴露的服務(wù)都是委托RuntimeInstance實(shí)現(xiàn),并且每次new一個VelocityEngine內(nèi)部都會有RuntimeInstance的一個實(shí)例被創(chuàng)建。而Velocity類調(diào)用了單例模式類RuntimeSingleton里面的方法,RuntimeSingleton又是RuntimeInstance的一個單例模式。

7.3 使用場景

  • 當(dāng)需要對外屏蔽一個系統(tǒng)的復(fù)雜性時候可以考慮使用門面模式對外提供簡單可讀性高的接口類。

  • 當(dāng)需要對外部暴露系統(tǒng)一部分權(quán)限的接口時候可以考慮使用門面模式減少系統(tǒng)權(quán)限。

  • 當(dāng)系統(tǒng)需要調(diào)用不同服務(wù)匯總后在對外提供服務(wù)時候可以考慮使用門面模式對外屏蔽細(xì)節(jié),只暴露一個接口。

八、裝飾器模式(Decorator Pattern)

8.1 介紹

裝飾器模式是一種結(jié)構(gòu)性模式,它的作用是對對象已有功能進(jìn)行增強(qiáng),但是不改變原有對象結(jié)構(gòu)。這避免了通過繼承方式進(jìn)行功能擴(kuò)充導(dǎo)致的類體系臃腫。

8.2 Spring中BeanDefinitionDecorator

先看下類圖:

如圖ScopedProxyBeanDefinitionDecorator實(shí)現(xiàn)了decorate方法用來對scope作用域?yàn)閞equest的bean定義進(jìn)行包裝。

具體時序圖為:

class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator { private static final String PROXY_TARGET_CLASS = "proxy-target-class"; @Override public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { boolean proxyTargetClass = true; if (node instanceof Element) { Element ele = (Element) node; if (ele.hasAttribute(PROXY_TARGET_CLASS)) { proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)); } } // 創(chuàng)建scoped的代理類,并注冊到容器 BeanDefinitionHolder holder = ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass); String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName()); parserContext.getReaderContext().fireComponentRegistered( new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName)); return holder; }}

關(guān)于ScopedProxyBeanDefinitionDecorator干啥用的呢:

   

其實(shí)就是處理

的,具體作用是包裝lavaPvgInfo的bean定義為ScopedProxyFactoryBean,作用是實(shí)現(xiàn)request作用域bean。

8.3 commons-collections包中ListUtils

如圖

ListUtils中的四個方法分別依賴list的四種裝飾器類對List功能進(jìn)行擴(kuò)充和限制。

其中FixedSizeList類通過禁止add/remove操作保證list的大小固定,但是可以修改元素內(nèi)容。

其中UnmodifiableList類通過禁用add,clear,remove,set,保證list的內(nèi)容不被修改。

其中SynchronizedList類通過使用Lock 來保證add,set,get,remove等的同步安全。

其中LazyList類則當(dāng)調(diào)用get方法發(fā)現(xiàn)list里面不存在對象時候,自動使用factory創(chuàng)建對象。

8.4 使用場景

  • 在不改變原有類結(jié)構(gòu)基礎(chǔ)上,新增或者限制或者改造功能時候。

九、適配器模式(Adapter Pattern)

9.1 介紹

適配器模式屬于結(jié)構(gòu)性模式,它為兩個不同接口之間互通提供了一種手段。

9.2 Spring中MethodInterceptor適配器

在Spring Aop框架中,MethodInterceptor接口被用來攔截指定的方法,對方法進(jìn)行增強(qiáng)。

大家都知道在Aop中每個advistor 里面會有一個advice具體做切面動作,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice這幾個advice,在XML 配置aop時候會指定,,,,其實(shí)內(nèi)部就是創(chuàng)建上面對應(yīng)的這些advice。

從圖知道AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice沒有實(shí)現(xiàn)MethodInterceptor接口,其他兩者則實(shí)現(xiàn)了該接口。而Spring Aop的方法攔截器卻必須是實(shí)現(xiàn)了MethodInterceptor的,所以Spring提供了對應(yīng)的適配器來適配這個問題,分別是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter。

看下DefaultAdvisorAdapterRegistry的 getInterceptors方法:

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List interceptors = new ArrayList(3); //從advistor中獲取advice Advice advice = advisor.getAdvice(); //如果實(shí)現(xiàn)了MethodInterceptor則直接加入,比如AspectJAroundAdvice,AspectJAfterAdvice if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } //否者看是否有當(dāng)前advice的適配器,首先檢驗(yàn)是否支持,支持則返回對應(yīng)的適配器 for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]);}

以MethodBeforeAdviceAdapter為例子看下:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); }}public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }}

可知MethodBeforeAdviceInterceptor繼承了MethodInterceptor作為了一個適配器內(nèi)部委托請求給MethodBeforeAdvice。

9.3 使用場景

  • 兩個系統(tǒng)交互時候由于接口參數(shù)不一樣沒辦法直接對接,則可以搞個適配器接口做參數(shù)轉(zhuǎn)換。

  • 適配器模式經(jīng)常是在一個系統(tǒng)或者設(shè)計(jì)已經(jīng)定型時候用的,而不是在初始設(shè)計(jì)時候。一般是因?yàn)椴挥绊懍F(xiàn)在業(yè)務(wù)情況下,通過適配方式統(tǒng)一接口

十、模板設(shè)計(jì)模式(Template Pattern)

10.1 前言

模板設(shè)計(jì)模式是一種行為設(shè)計(jì)模式,它使用一個抽象類定義了一個模板,這個模板里面定義了一系列的接口,子類則只需要繼承該抽象類并且根據(jù)需要重寫一部分接口。

10.2 ibatis2中AbstractDAOTemplate

如圖AbstractDAOTemplate是抽象模板類,里面定義了configure方法,configure方法里面定義了好多protected方法,其中就有些是抽象方法。類SpringDAOTemplate,IbatisDAOTemplate,GenericCIDAOTemplate,GenericSIDAOTemplate則繼承了AbstractDAOTemplate類并重寫了一部分方法。

10.3 Tomcat中Digester里面的Rule

tomcat中的Digester是為了解析server.xml的,其中每個元素都有一個解析規(guī)則就是Rule ,類圖如下:

如圖:Rule是抽象類,對于每個解析的節(jié)點(diǎn)來說Rule提供了解析所需所有的方法,而他的子類則根據(jù)自己的特殊性重寫一部分方法來支持自己的特性。

10.4 Tomcat中Endpoint

如圖AbstractEndpoint是個抽象類,定義了Endpoint的所有接口,然后JIoEndpoint繼承了該類并且重寫了一部分重要的方法實(shí)現(xiàn)了BIO方式endpoint,NioEndpoint則重寫了方法實(shí)現(xiàn)了NIO的endpoint。

10.5使用場景

  • 當(dāng)多個子類具有共同的操作流程邏輯,并且其中某些流程節(jié)點(diǎn)操作需要自己定制化時候。

十一、 建造者模式(Builder Pattern)

11.1 前言

建造者模式是一種創(chuàng)建型模式,將一個復(fù)制對象的創(chuàng)建屏蔽到接口內(nèi)部,用戶使用時候只需要傳遞固定的參數(shù),內(nèi)部就會執(zhí)行復(fù)雜邏輯后返回給用戶需要的對象,用戶不需要知道創(chuàng)建的細(xì)節(jié)。

11.2 Mybatis中的SqlSessionFactoryBuilder

如圖mybaits中的SqlSessionFactoryBuilder就是典型的創(chuàng)建者模式,他內(nèi)部有多個build方法,根據(jù)參數(shù)的不同創(chuàng)建出SqlSessionFactory對象,使用者只需要傳遞具體參數(shù)而不用關(guān)心內(nèi)部是如何創(chuàng)建出需要的對象的。SqlSessionFactoryBean大家應(yīng)該很熟悉,在xml里面配置的。

11.3 使用場景

  • 當(dāng)一個對象比較復(fù)雜并且容易出錯時候,可以考慮這種模式去屏蔽創(chuàng)造細(xì)節(jié)。

十二、 觀察者模式(Observer Pattern)

12.1 前言

觀察者模式是一種行為模式,它定義了當(dāng)一個對象的狀態(tài)或者屬性發(fā)生變化時候,通知其他對這些狀態(tài)感興趣的對象。觀察者模式也叫發(fā)布-訂閱模式,就是說當(dāng)你訂閱了摸一個主體時候,如果發(fā)布者改變了主題內(nèi)容,那么所有訂閱這個主體者都會受到通知。

12.2 Spring中ApplicationListener

如圖 黃色部分的listener們可以認(rèn)為是訂閱者,紅色的context是發(fā)布者,context在IOC不同狀態(tài)會給這些訂閱者發(fā)布不同的消息通知訂閱者容器狀態(tài)。藍(lán)色的為具體的事件(這里為容器不同狀態(tài)),其中ContextRefreshedEvent是IOC刷新完成(也就是bean解析完成,創(chuàng)建完畢并且autowired完成)后的事件這個經(jīng)常用。

這里context并不是直接來管理黃色的listener訂閱者的,而是委托給了綠色的部分,該部分是可以增加刪除訂閱者,并且發(fā)布事件給訂閱者。

其實(shí)Tomact中的Lifecycle也是這種機(jī)制,這里不再贅述。

12.3 使用場景

  • 滿足發(fā)布-訂閱條件的,當(dāng)一個對象狀態(tài)或者屬性變化,需要把這種變化通知到訂閱者時候。

十三、命令模式(Command Pattern)

13.1 介紹

命令模式是一種行為模式,通過把命令封裝為一個對象,命令發(fā)送者把命令對象發(fā)出后,就不去管是誰來接受處理這個命令,命令接受者接受到命令對象后進(jìn)行處理,也不用管命令是誰發(fā)出的,所以命令模式實(shí)現(xiàn)了發(fā)送者與接受者之間的解耦,而具體把命令發(fā)送給誰還需要一個控制器。

13.2 Tomcat中命令模式

tomcat作為一個服務(wù)器本身會接受外部大量請求,當(dāng)一個請求過來后tomcat根據(jù)域名去找對應(yīng)的host,找到host后會根據(jù)應(yīng)用名去找具體的context(應(yīng)用),然后具體應(yīng)用處理請求。對于具體host來說他不關(guān)心這個請求是誰給的,對應(yīng)請求來說他不必關(guān)心誰來處理,但是兩者是通過request封裝請求對象進(jìn)行關(guān)聯(lián)起來。

tomcat中Connector作為命令發(fā)出者,Connector接受到請求后把請求內(nèi)容封裝為request對象(命令對象),然后使用CoyoteAdapter作為分發(fā)器把請求具體發(fā)配到具體的host,host在根據(jù)request對象找到具體的context,至此找到了具體的應(yīng)用,交給具體應(yīng)用處理。

另外對于使用springmvc的應(yīng)用來說,上面找到具體應(yīng)用,但是具體交給那個controller來處理那,這是不是也是命令模式的使用那。

13.3 使用場景

  • 當(dāng)事件發(fā)送者和接受者直接需要完全解耦(直接并不存在引用關(guān)系)時候。

十四、總結(jié)

設(shè)計(jì)模式中每一個模式都描述了在我們工作中不斷重復(fù)發(fā)生的問題,以及問題的解決方案,所以真正掌握設(shè)計(jì)模式可以避免我們做不必要的重復(fù)勞動。


標(biāo)題名稱:【分享】我在阿里工作十年里接觸過的Java框架設(shè)計(jì)模式
網(wǎng)頁網(wǎng)址:http://www.5511xx.com/article/cdjssco.html