精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

論 Spring 框架所運(yùn)用的設(shè)計(jì)模式

開發(fā)
本文直接從底層源碼設(shè)計(jì)和實(shí)現(xiàn)的角度,詳盡分析了 Spring 中涉及的設(shè)計(jì)模式,希望對(duì)你有幫助。

在當(dāng)今軟件開發(fā)的廣闊領(lǐng)域中,Spring 框架無疑占據(jù)著重要的一席之地。它以其強(qiáng)大的功能和靈活性,成為眾多開發(fā)者的得力助手。而在 Spring 框架的背后,蘊(yùn)含著一系列精妙絕倫的設(shè)計(jì)模式,這些設(shè)計(jì)模式猶如隱藏的智慧密碼,賦予了框架無盡的活力與魅力。

當(dāng)我們深入探究 Spring 框架時(shí),就仿佛開啟了一扇通往軟件設(shè)計(jì)藝術(shù)殿堂的大門。其中的設(shè)計(jì)模式不僅是代碼組織和架構(gòu)的精巧構(gòu)建,更是對(duì)軟件開發(fā)理念的深刻詮釋。它們巧妙地解決了各種復(fù)雜問題,實(shí)現(xiàn)了代碼的高效復(fù)用、模塊的松散耦合以及系統(tǒng)的良好擴(kuò)展性。通過對(duì) Spring 框架涉及的設(shè)計(jì)模式的剖析,我們將領(lǐng)略到設(shè)計(jì)智慧的熠熠光輝,感受它們?nèi)绾卧谲浖澜缰醒堇[出一場場精彩絕倫的代碼之舞,為構(gòu)建高質(zhì)量、可維護(hù)的軟件系統(tǒng)奠定堅(jiān)實(shí)基礎(chǔ)。讓我們一同踏上這場探索 Spring 框架設(shè)計(jì)模式的奇妙之旅,去揭示其中的奧秘與精彩。

一、關(guān)于設(shè)計(jì)模式的一些只是鋪墊

1.軟件設(shè)計(jì)有哪些原則?

整體來說有七大原則:

  • 開閉原則:對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
  • 里氏轉(zhuǎn)換:子類繼承父類時(shí),除添加新的方法完成新增功能外,盡量不要重寫父類的方法。
  • 依賴倒置: 高層類應(yīng)該依賴于底層類的抽象而不是具體。
  • 合成復(fù)用:盡量使用對(duì)象組合/聚合,而不是繼承關(guān)系達(dá)到軟件復(fù)用的目的。
  • 單一職責(zé):不要多于一個(gè)導(dǎo)致類變更的原因。
  • 接口原則:用多個(gè)接口確定類的行為,而不是一個(gè)總接口定義所有行為。
  • 迪米特法則:最少知道原則,一個(gè)類應(yīng)該盡可能減少對(duì)其他類的了解,避免類之間過度耦合。(其他類應(yīng)該封裝一個(gè)方法提供的該類使用)

2.設(shè)計(jì)模式分為哪幾類?有哪些設(shè)計(jì)模式

分類:

  • 創(chuàng)建型模式:創(chuàng)建型模式主要用于創(chuàng)建對(duì)象。
  • 結(jié)構(gòu)型模式:主要用于處理類或?qū)ο蟮慕M合。
  • 行為型模式:主要用于描述對(duì)類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)。

創(chuàng)建型模式:

  • 單例模式:確保類有且只有一個(gè)對(duì)象被創(chuàng)建。
  • 抽象工廠模式:允許客戶創(chuàng)建對(duì)象的宗族,而無需指定他們的具體類。
  • 建造者模式:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,讓同樣的構(gòu)建過程而已創(chuàng)建不同的表示。
  • 工廠方法模式:由類決定要?jiǎng)?chuàng)建的具體類是哪一個(gè)。
  • 原型模式:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過拷貝這個(gè)原型來創(chuàng)建新的對(duì)象。

結(jié)構(gòu)型模式:

  • 適配器模式:封裝對(duì)象,并提供不同的接口。
  • 橋接模式:將抽象部分和實(shí)現(xiàn)部分分離,讓他們獨(dú)立的變化。
  • 裝飾模式:包裝一個(gè)對(duì)象,提供新的行為。
  • 組合模式:客戶用一致的方式處理對(duì)象集合和單個(gè)對(duì)象。
  • 外觀模式:簡化一群類的接口。
  • 享元模式:運(yùn)用共享技術(shù)有效的支持大量細(xì)粒度的對(duì)象。
  • 代理模式:包裝對(duì)象,以控制對(duì)此對(duì)象的訪問。

行為型模式:

  • 模板方法模式:定義一個(gè)操作算法的總體架構(gòu),將一些步驟的實(shí)現(xiàn)放在子類中。
  • 命令模式:封裝請求成為對(duì)象。
  • 迭代器模式:在對(duì)象的集合之中游走,而不是暴露集合的實(shí)現(xiàn)。
  • 觀察者模式:讓對(duì)象能夠在狀態(tài)改變時(shí)被通知。
  • 中介者模式:用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使各個(gè)對(duì)象不需要顯示的相互引用,從而使其耦合松散,而且可以獨(dú)立地改變他們之間的交互。
  • 備忘錄模式:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。 以后就可以將該對(duì)象恢復(fù)到保存狀態(tài)。
  • 解釋器模式:介紹給定一個(gè)語言,定義它的文法的一種表示,并定義一個(gè)解釋器, 該解釋器使用該表示來解釋語言中的句子。
  • 狀態(tài)模式:封裝了基于狀態(tài)的行為,并使用委托在行為之間的切換。
  • 策略模式:封裝可以互換的行為,并使用委托來決定要使用哪一個(gè)。
  • 責(zé)任鏈模式:為了解除請求的發(fā)送者和接收者之間的耦合,使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請求。將這些處理對(duì)象連成一個(gè)鏈,并沿著這個(gè)鏈傳遞該請求,直到一個(gè)對(duì)象處理它。
  • 訪問者模式:一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

二、詳解Spring核心中的設(shè)計(jì)模式

1.為什么說Spring框架中的IOC是解耦的

從代碼層面來說,Spring通過控制反轉(zhuǎn)將對(duì)象之類依賴關(guān)系交由容器管理,如下所示我們的AService  依賴BService ,BService 可能還會(huì)依賴于CService 層層遞進(jìn),如果是傳統(tǒng)編碼,我們可能需要通過硬編碼的方式完成AService  的構(gòu)建。 而Spring通過IOC思想,在初始化階段將所有對(duì)象都交由三級(jí)緩存管理,將所有java bean初始化責(zé)任的實(shí)現(xiàn)細(xì)節(jié)轉(zhuǎn)移給Spring,使用時(shí)也只需指明接口類型,接口實(shí)現(xiàn)也無需關(guān)心,只需在配置層面中指定,而非通過硬編碼完成依賴管理:

所以我們使用時(shí)只需幾個(gè)簡單的配置和注解即可完成各種復(fù)雜的bean的依賴管理,這也就是開發(fā)層面對(duì)象依賴關(guān)系管理的解耦:

@Service("aService")
@Slf4j
public class AService  {

    @Autowired
    private BService bService;

   //......

}

從使用層面來說,Spring中的IOC也用到類似于門面模式的思想,將工具類的使用和創(chuàng)建剝離,整個(gè)工具類的創(chuàng)建過程對(duì)使用者來說是透明解耦的。

例如我們需要使用日志框架,在spring中我們只需給出簡單的配置,框架即在運(yùn)行時(shí)基于給定配置完成對(duì)應(yīng)的日志工具的注入(可以是log4j可以是slf4j或者其他日志框架),程序啟動(dòng)后即可直接使用功能,無需關(guān)心創(chuàng)建和實(shí)現(xiàn):

2.Spring源碼中涉及的簡單工廠模式

簡單工廠模式的思想就是對(duì)外屏蔽創(chuàng)建對(duì)象的細(xì)節(jié),將對(duì)象的獲取統(tǒng)一內(nèi)聚到一個(gè)工廠類中,這一點(diǎn)在Spring中的ApplicationContext 發(fā)揮的淋漓盡致。 我們都知道Spring將所有java bean統(tǒng)一交由三級(jí)緩存進(jìn)行管理,使用時(shí)我們可以通過上下文或者需要的java bean,用戶只需按需要傳遞給工廠對(duì)應(yīng)的bean名稱即可得到自己需要的對(duì)象即可:

對(duì)應(yīng)的我們也給出使用示例:

@Autowired
    private ApplicationContext applicationContext;

    public Object getBean(String beanName) {
        Object bean = applicationContext.getBean(beanName);
        return bean;
    }

3.Spring中的工廠方法模式

工廠方法模式適用于想讓工廠專注創(chuàng)建一個(gè)對(duì)象的場景,相較于簡單工廠模式,工廠方法模式思想是提供一個(gè)工廠的接口,開發(fā)者根據(jù)這個(gè)規(guī)范創(chuàng)建不同的工廠,然后按需使用不同的工廠創(chuàng)建不同的類即可。這種做法確保了工廠類也遵循開閉原則。

Spring中的FactoryBean就是工廠方法模式的典型實(shí)現(xiàn),如果我們希望容器中能夠提供一個(gè)可以創(chuàng)造指定類的工廠,那么我們就可以通過FactoryBean實(shí)現(xiàn)。 例如我們希望有一個(gè)工廠可以創(chuàng)建經(jīng)理,另一個(gè)工廠可以創(chuàng)建主管。那么我們就可以通過FactoryBean實(shí)現(xiàn)。 實(shí)現(xiàn)步驟如下,由于經(jīng)理和主管都是雇員類,所以我們創(chuàng)建一個(gè)雇員類:

//雇員類
public class EmployeeDTO {

 private Integer id;
 private String firstName;
 private String lastName;
 private String designation;

 //Setters and Getters are hidden behind this comment.


 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName
    + ", lastName=" + lastName + ", type=" + designation + "]";
 }
}

然后我們繼承FactoryBean接口實(shí)現(xiàn)一個(gè)工廠方法類,如下所示,可以看到如果我們可以根據(jù)傳入的designation決定創(chuàng)建的雇員類型。

public class EmployeeFactoryBean extends AbstractFactoryBean<Object> {
 // 根據(jù)這個(gè)值決定創(chuàng)建主管還是經(jīng)理
 private String designation;

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

 //This method will be called by container to create new instances
 @Override
 protected Object createInstance() throws Exception {
  EmployeeDTO employee = new EmployeeDTO();
  employee.setId(-1);
  employee.setFirstName("dummy");
  employee.setLastName("dummy");
  //Set designation here
  employee.setDesignation(designation);
  return employee;
 }

 //This method is required for autowiring to work correctly
 @Override
 public Class<EmployeeDTO> getObjectType() {
  return EmployeeDTO.class;
 }
}

兩種雇員的配置如下所示:

<!--factoryBean使用示例-->
<!--經(jīng)理工廠-->
 <bean id="manager"  class="com.study.service.EmployeeFactoryBean">
  <property name="designation" value="Manager" />
 </bean>
<!--主管工廠-->
 <bean id="director"  class="com.study.service.EmployeeFactoryBean">
  <property name="designation" value="Director" />
 </bean>

如果我們想創(chuàng)建director(主管)的工廠,那么我們的代碼就可以這樣使用,注意我們獲取bean時(shí)必須使用&,否則獲得的就不是EmployeeFactoryBean,則是EmployeeDTO

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
  Object factory =  context.getBean("&director");
  System.out.println(factory);
  //工廠方法模式,通過單一職責(zé)的工廠獲取專門的類
  System.out.println(((EmployeeFactoryBean) factory).getObject());

當(dāng)然,如果想直接獲取高管或者經(jīng)理,獲取bean時(shí)不加&即可代碼如下所示即可:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

  EmployeeDTO manager = (EmployeeDTO) context.getBean("manager");
  System.out.println(manager);

  Object director =  context.getBean("director");
  System.out.println(director);

4.工廠方法模式相較于簡單工廠模式的優(yōu)缺點(diǎn)

工廠方法模式的優(yōu)點(diǎn):

  • 符合開閉原則,相較于上面說到的簡單工廠模式來說,我們無需因?yàn)樵黾右粋€(gè)類型而去修改工廠代碼,我們完全可以通過實(shí)現(xiàn)一個(gè)新的工廠實(shí)現(xiàn)。
  • 更符合單一職責(zé)的原則,對(duì)于單個(gè)類型創(chuàng)建的工廠邏輯更加易于維護(hù)。

缺點(diǎn):

  • 針對(duì)特定類型都需要?jiǎng)?chuàng)建特定工廠,創(chuàng)建的類會(huì)增加,導(dǎo)致項(xiàng)目變得臃腫。
  • 因?yàn)楣S方法的模式結(jié)構(gòu),維護(hù)的成本相對(duì)于簡單工廠模式會(huì)更高一些。

5.單例模式在Java中的使用優(yōu)勢

節(jié)省沒必要的創(chuàng)建對(duì)象的時(shí)間,由于是單例的對(duì)象,所以創(chuàng)建一次后就可以一直使用了,所以我們無需為了一個(gè)重量級(jí)對(duì)象的創(chuàng)建而耗費(fèi)大量的資源。

由于重量級(jí)對(duì)象的創(chuàng)建次數(shù)少了,所以我們就避免了沒必要的GC。從而降低GC壓力,避免沒必要的STW(Stop the World)導(dǎo)致的GC停頓。

6.Spring中單例模式的實(shí)現(xiàn)

Spring中獲取對(duì)象實(shí)例的方法即DefaultSingletonBeanRegistry中的getSingleton就是典型的Double-Checked Locking單例模式代碼:

@Nullable
 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // Quick check for existing instance without full singleton lock
  Object singletonObject = this.singletonObjects.get(beanName);
  //一級(jí)緩存沒有需要的bean,進(jìn)入該邏輯
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   singletonObject = this.earlySingletonObjects.get(beanName);
   if (singletonObject == null && allowEarlyReference) {
    //二級(jí)對(duì)象也沒有,上鎖進(jìn)入創(chuàng)建邏輯
    synchronized (this.singletonObjects) {
     // 再次檢查一級(jí)緩存也沒有,避免重復(fù)創(chuàng)建問題
     singletonObject = this.singletonObjects.get(beanName);
     if (singletonObject == null) {
      //......
      //創(chuàng)建對(duì)象存入二級(jí)緩存中
      }
     }
    }
   }
  }
  return singletonObject;
 }

7.Spring中的代理模式

代理模式解耦了調(diào)用者和被調(diào)用者的關(guān)系,同時(shí)通過對(duì)原生類型的代理進(jìn)行增強(qiáng)易于拓展和維護(hù),Spring AOP就是通過代理模式實(shí)現(xiàn)增強(qiáng)切入,我們就以JDK代理為例查看Spring中的實(shí)現(xiàn):

public Object getProxy(@Nullable ClassLoader classLoader) {
  // 忽略代碼
  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  //通過被代理的類的接口以及增強(qiáng)邏輯創(chuàng)建一個(gè)增強(qiáng)的用戶所需要的類
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
 }

查看newProxyInstance的實(shí)現(xiàn)即可看到j(luò)dk代理的傳統(tǒng)創(chuàng)建細(xì)節(jié)即拿到被代理的類類型和需要增強(qiáng)后的方法實(shí)現(xiàn)InvocationHandler 通過反射完成代理類創(chuàng)建:

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
     //......
       //獲取接口類類型
        Class<?> cl = getProxyClass0(loader, intfs);

      //......
      //從緩存中獲取代理類的構(gòu)造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
           //......
           //基于InvocationHandler 和構(gòu)造方法完成代理類創(chuàng)建
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
           //......
        } catch (InvocationTargetException e) {
           //......
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

8.Spring中的模板方法模式

模板方法模式即固定一個(gè)算法骨架,抽象出某些可變的方法交給子類實(shí)現(xiàn),Spring的AbstractApplicationContext的refresh方法就是典型模板方法模式,

@Override
 public void refresh() throws BeansException, IllegalStateException {
  // 給容器refresh加鎖,避免容器處在refresh階段時(shí),容器進(jìn)行了初始化或者銷毀的操作
  synchronized (this.startupShutdownMonitor) {
   // .........

   try {
    // .........
    //定義了相關(guān)接口給用戶實(shí)現(xiàn),該方法會(huì)通過回調(diào)的方式調(diào)用這些方法,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
    invokeBeanFactoryPostProcessors(beanFactory);

    // 注冊攔截bean創(chuàng)建過程的BeanPostProcessor,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
    registerBeanPostProcessors(beanFactory);

    //模板方法的體現(xiàn),用戶可自定義重寫該方法
    onRefresh();

    //.......
   }

   // .......
  }
 }

9.模板方法模式的優(yōu)劣勢

優(yōu)勢很明顯:

  • 算法骨架由父類定義,封裝不變,擴(kuò)展可變。
  • 子類只需按需實(shí)現(xiàn)抽象類即可,易于擴(kuò)展維護(hù)。
  • 提取了公共代碼,避免編寫重復(fù)代碼。

缺點(diǎn):

  • 可讀性下降
  • 可能會(huì)導(dǎo)致子類泛濫問題。

10.Spring中的觀察者模式

觀察者模式是一種行為型模式。 它表示的是一種主題與訂閱者之間具有依賴關(guān)系,當(dāng)訂閱者訂閱的主題狀態(tài)發(fā)生改變,會(huì)發(fā)送通知給響應(yīng)訂閱者,觸發(fā)訂閱者的響應(yīng)操作。

Spring 事件驅(qū)動(dòng)模型就是觀察者模式很經(jīng)典的一個(gè)應(yīng)用。Spring 事件驅(qū)動(dòng)模型非常有用,在很多場景都可以解耦我們的代碼。比如我們每次發(fā)布一個(gè)通知就需要某個(gè)用戶做出收到的響應(yīng),這個(gè)時(shí)候就可以利用觀察者模式來解決這個(gè)問題。

首先我們需要定義一個(gè)事件類:

public class DemoEvent extends ApplicationEvent {
    private String msg;

    public DemoEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

然后創(chuàng)建一個(gè)監(jiān)聽器集成Spring框架的ApplicationListener,對(duì)DemoEvent進(jìn)行監(jiān)聽:

@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
    private static Logger logger = LoggerFactory.getLogger(DemoListener.class);

    @Override
    public void onApplicationEvent(DemoEvent event) {

        logger.info("收到消息,消息內(nèi)容:{}", event.getMsg());
    }
}

這樣我們發(fā)布事件后,監(jiān)聽器就接受并處理返回結(jié)果了:

@Autowired
    private ApplicationContext applicationContext;


  @Test
    public void sendMsg() {
        DemoEvent event = new DemoEvent(this, "你好");
        applicationContext.publishEvent(event);
    }

對(duì)應(yīng)輸出結(jié)果如下所示:

2022-11-22 13:03:15.814  INFO 15600 --- [           main] com.example.demo.DemoListener            : 收到消息,消息內(nèi)容:你好

11.Spring中用到的適配器模式

適配器模式有用在在DisposableBeanAdapter適配統(tǒng)一處理bean銷毀上,因?yàn)槲覀僢ean銷毀方法可以通過xml配置也可以通過繼承DisposableBean接口實(shí)現(xiàn),所以這兩種不同的方法在銷毀時(shí)處理方式可能不一樣,所以我們可以通過適配器模式將這兩個(gè)處理邏輯封裝成統(tǒng)一適配器進(jìn)行處理

@Override
 public void destroy() {
  //......
  //如果是接口實(shí)現(xiàn)則執(zhí)行該類實(shí)現(xiàn)的destroy方法
  if (this.invokeDisposableBean) {
   //......
   try {
    if (System.getSecurityManager() != null) {
    //......
    }
    else {
    //
     ((DisposableBean) this.bean).destroy();
    }
   }
   catch (Throwable ex) {
    //......
   }
  }
  
  //如果有注解或者xml配置的方法,則走invokeCustomDestroyMethod進(jìn)行調(diào)用
  if (this.destroyMethod != null) {
   invokeCustomDestroyMethod(this.destroyMethod);
  }
  else if (this.destroyMethodName != null) {
   Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
   if (methodToInvoke != null) {
    invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
   }
  }
 }

12.Spring中的裝飾者模式

裝飾者模式即通過組合的方式對(duì)原有類的行為進(jìn)行一些擴(kuò)展操作即在開閉原則下的一種結(jié)構(gòu)型設(shè)計(jì)模式,就以Spring中的TransactionAwareCacheDecorator為例,它就是實(shí)現(xiàn)緩存支持事務(wù)的功能,繼承緩存接口,并將目標(biāo)緩存類組合進(jìn)來,保證原有類不被修改的情況下實(shí)現(xiàn)功能的擴(kuò)展:

//繼承Cache 類
public class TransactionAwareCacheDecorator implements Cache {

 //行為需要擴(kuò)展的目標(biāo)類
 private final Cache targetCache;



// 從接口那里獲得的put方法,通過對(duì)targetCache的put進(jìn)行進(jìn)一步封裝實(shí)現(xiàn)功能的包裝
 @Override
 public void put(final Object key, @Nullable final Object value) {
  if (TransactionSynchronizationManager.isSynchronizationActive()) {
   TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
    @Override
    public void afterCommit() {
     TransactionAwareCacheDecorator.this.targetCache.put(key, value);
    }
   });
  }
  else {
   this.targetCache.put(key, value);
  }
 }

}

三、更多關(guān)于設(shè)計(jì)模式

1.什么是策略模式

策略模式是一種行為模式,它的作用主要是用于封裝那些動(dòng)作一致,但是具體實(shí)現(xiàn)不一致的場景。例如我們現(xiàn)在有一個(gè)審核的動(dòng)作,不同的人審核的方式不同。而且審核的行為會(huì)隨著時(shí)間推移不斷增加,單純使用if else去維護(hù)會(huì)使得代碼變得非常凌亂。 這時(shí)候使用策略模式定義一下相同的行為,讓子類去實(shí)現(xiàn)不同的策略,這樣的方式是最利于拓展的。

2.策略模式在Spring中如何使用

使用策略模式前,我們先需要使用接口固定一下策略的定義,例如我們現(xiàn)在要?jiǎng)?chuàng)建一個(gè)生成對(duì)象的策略createObj:

public interface CreateObjStrategy {

    Object createObj();
}

對(duì)應(yīng)我們分別寫一個(gè)創(chuàng)建字符串對(duì)象和json對(duì)象的策略代碼:

@Component("createObj_str")
public class CreateStrObjStrategy implements CreateObjStrategy {
    @Override
    public Object createObj() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "xiaoming");
        return JSONUtil.toJsonStr(map);
    }
}

@Component("createObj_json")
public class CreateJsonObjStrategy implements CreateObjStrategy {
    @Override
    public Object createObj() {
        JSONObject obj = new JSONObject();
        obj.put("name", "zhangsan");
        return obj;
    }
}

到此為止,我們已經(jīng)完成了所有的策略的封裝,按照原生的策略模式的做法它會(huì)通過一個(gè)上下文來配置當(dāng)前策略,就像下面這張?jiān)O(shè)計(jì)圖:

對(duì)應(yīng)我們給出封裝的代碼示例:

public class CreateJsonObjContext {

    private CreateObjStrategy createObjStrategy;

    public CreateJsonObjContext(CreateObjStrategy strategy) {
        this.createObjStrategy = strategy;
    }


    public Object createObj() {
        return createObjStrategy.createObj();
    }


}

實(shí)際上有了Spring我們無需進(jìn)行顯示聲明創(chuàng)建了,我們可以通過配置、注解等方式指明本地程序需要注入的CreateObjStrategy 實(shí)現(xiàn),加載上下文的時(shí)候通過ApplicationContextAware這樣的擴(kuò)展點(diǎn)把bean取出來設(shè)置到CreateJsonObjContext 中:

@Component
public class CreateJsonObjContext implements ApplicationContextAware {

    private CreateObjStrategy createObjStrategy;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //從容器中拿到由我們配置后容器中所設(shè)置的CreateObjStrategy設(shè)置到Context中
        CreateObjStrategy bean = applicationContext.getBean(CreateObjStrategy.class);
        createObjStrategy = bean;
    }

    public Object createObj() {
        return createObjStrategy.createObj();
    }

    
}

3.Spring中策略模式的運(yùn)用

最典型的就時(shí)InstantiationStrategy,Spring為其實(shí)現(xiàn)了兩種不同的策略,分別是CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy,在Spring通過實(shí)例化java bean的時(shí)候其內(nèi)部就會(huì)通過getInstantiationStrategy從上下文中獲取初始化策略instantiationStrategy,然后調(diào)用instantiationStrategy的instantiate完成bean的創(chuàng)建:

對(duì)應(yīng)的我們也給出AbstractAutowireCapableBeanFactory中instantiate實(shí)例化bean的實(shí)現(xiàn)印證這一說法:

private Object instantiate(String beanName, RootBeanDefinition mbd,
   @Nullable Object factoryBean, Method factoryMethod, Object[] args) {

  try {
  
   else {
   //通過getInstantiationStrategy獲取上下文中對(duì)應(yīng)的創(chuàng)建策略完成bean的創(chuàng)建
    return this.beanFactory.getInstantiationStrategy().instantiate(
      mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
   }
  }
  catch (Throwable ex) {
   //......
  }
 }


責(zé)任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關(guān)推薦

2025-05-09 09:05:00

Spring框架設(shè)計(jì)模式

2023-07-03 07:39:43

Spring框架設(shè)計(jì)模式

2010-06-11 14:55:20

2020-07-30 08:10:08

框架設(shè)計(jì)Spring Secu

2023-03-03 13:10:15

2009-06-22 16:34:30

框架架構(gòu)設(shè)計(jì)模式

2009-06-24 17:21:23

JSF框架設(shè)計(jì)模式

2009-06-22 16:24:33

JSF框架中使用的設(shè)計(jì)

2020-09-04 14:10:31

架構(gòu)軟件互聯(lián)網(wǎng)

2011-04-22 09:26:57

MVC設(shè)計(jì)

2017-02-13 13:10:35

JavaScript設(shè)計(jì)模式

2019-08-23 11:58:07

Java框架架構(gòu)

2011-07-08 14:01:26

Windows安全

2024-11-26 14:29:48

2022-09-21 09:01:27

Spring設(shè)計(jì)模式框架,

2024-06-19 16:02:46

2021-10-29 15:01:59

前端開發(fā)技術(shù)

2009-07-30 14:03:04

ASP.NET中的se

2021-04-19 21:25:48

設(shè)計(jì)模式到元

2025-06-03 04:00:00

Spring框架配置
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产精品一级二级| 亚洲国产成人精品女人久久久| 亚洲午夜精品久久久久久久久久久久| 日本黄xxxxxxxxx100| 91视频在线视频| 久久午夜影院| 国产91富婆露脸刺激对白| 综合国产在线视频| 搡女人真爽免费午夜网站| 亚洲精品97久久中文字幕| 日韩成人a**站| 色综合久久综合中文综合网| 国产欧美日韩视频一区二区三区| 欧美成人综合色| 欧美2区3区4区| 国产精品久久久久一区| 国产精品69精品一区二区三区| 久久人人妻人人人人妻性色av| 性欧美ⅴideo另类hd| 在线中文一区| 欧美一级欧美一级在线播放| 一区中文字幕在线观看| 国产又粗又猛视频| 天天天综合网| 91精品国产综合久久福利软件 | 亚洲另类在线观看| 久久1电影院| 欧美日韩高清一区二区不卡 | 久久久久亚洲av片无码v| 在线免费看黄| 国产专区欧美精品| 欧美成人精品激情在线观看 | www.avtt| 天堂av手机版| 老司机免费视频久久| 亚洲免费成人av电影| 无码日韩人妻精品久久蜜桃| porn视频在线观看| 精彩视频一区二区三区| 欧美成人国产va精品日本一级| 国产精品天天干| 色综合一区二区日本韩国亚洲| 亚洲天堂免费看| 国产一区二区中文字幕免费看| 国产欧美熟妇另类久久久 | 裸体女人亚洲精品一区| 美女流白浆视频| av电影免费在线看| 久久久www成人免费毛片麻豆| 国产精品日日摸夜夜添夜夜av| 紧身裙女教师波多野结衣| 国产厕拍一区| 日本精品视频一区二区三区| 超碰免费在线公开| 成黄免费在线| 国产精品人成在线观看免费| 欧美午夜精品久久久久久蜜| 国产美女免费视频| 精品一区二区三区视频在线观看| 久久人人爽人人爽人人片av高清| 国产手机在线观看| 狂野欧美xxxx韩国少妇| 91精品婷婷国产综合久久性色| 黄色大片中文字幕| shkd中文字幕久久在线观看| 国产欧美日本一区视频| 99久久免费国| 日韩xxx视频| 亚洲视频日本| 久久精品电影一区二区| 国产肉体xxxx裸体784大胆| 欧美xxxx性| 欧美日韩亚洲精品内裤| 日本免费黄色小视频| 性欧美video高清bbw| 午夜一区二区三区在线观看| 一区不卡视频| 狠狠色伊人亚洲综合网站l| 国产精品综合久久| 国产精品日韩在线观看| 国产一区二区三区四区视频 | 亚洲欧美日本一区| 欧美男gay| 精品女同一区二区| 国产九九在线观看| 自拍视频在线看| 一区二区三区在线免费播放| 亚洲在线色站| 三级福利片在线观看| 精品国产精品三级精品av网址| 视频一区二区视频| 国产乱妇乱子在线播视频播放网站| 国产精品久久精品日日| 日韩av高清在线播放| 深夜福利视频在线免费观看| 麻豆中文一区二区| 国产91精品网站| 亚洲高清毛片一区二区| 欧美日一区二区三区在线观看国产免| 中文字幕精品视频| 欧美成欧美va| 日韩精品一二三四| 国产a级全部精品| 国产欧美日韩成人| 国产色爱av资源综合区| 欧美动漫一区二区| av中文字幕在线观看| 国产精品福利一区二区三区| 欧美一级视频在线播放| 欧美理论电影| 亚洲影院免费观看| 艳母动漫在线免费观看| www.色在线| 色综合天天综合网国产成人综合天 | 91久久中文字幕| 国产精品久久久久久久一区二区 | 亚洲精品电影网在线观看| 日本不卡视频一区| 牛牛影视久久网| 亚洲乱码国产乱码精品精天堂| 国内毛片毛片毛片毛片毛片| 婷婷综合久久| 日韩av大片免费看| 六月丁香色婷婷| 91小视频在线观看| 欧美日产一区二区三区在线观看| 性国产高清在线观看| 欧美日韩五月天| 波多野结衣电影免费观看| 欧美日韩中字| 麻豆乱码国产一区二区三区| 国产一级精品毛片| 91美女视频网站| 国产日韩av网站| 99精品在免费线中文字幕网站一区| 亚洲国产精品人人爽夜夜爽| 欧美人妻一区二区| 亚洲美女少妇无套啪啪呻吟| 欧美最猛性xxxxx免费| 久久久精品毛片| 久88久久88久久久| 日本在线一区| 三上悠亚一区二区| 4438成人网| 国产免费嫩草影院| 黄色在线成人| 国产v亚洲v天堂无码| 免费一级毛片在线观看| 一区免费观看视频| 国产不卡一区二区视频| 91精品入口| 国产一区二区三区视频免费| 免费黄色网址在线| 久久久久久久久久看片| 免费观看成人网| 精品国产欧美日韩| 欧美在线亚洲在线| 国产免费永久在线观看| 亚洲精品中文字幕在线观看| 成人在线看视频| 精品视频在线一区| 九九热这里只有精品6| 久久精品国产成人av| 91丨porny丨首页| 久久久久久久少妇| 久久中文字幕av一区二区不卡| 久久久中精品2020中文| 午夜在线观看视频18| 最新成人av在线| 91热视频在线观看| 精品国产一区二区三区小蝌蚪 | 狠狠干视频网站| 桃花岛成人影院| 综合欧美国产视频二区| 亚洲综合免费视频| 久久午夜老司机| 日本国产中文字幕| 牛牛影视久久网| 国产精品入口尤物| 在线观看电影av| 欧美日韩亚洲综合| 免费在线视频观看| 久久综合狠狠综合久久综合88| 校园春色 亚洲色图| 日韩精品免费一区二区夜夜嗨| 欧美成人免费播放| 免费观看a视频| 亚洲精品免费一二三区| 国产xxxx视频| 最新日韩欧美| 超碰97国产在线| 中文字幕21页在线看| 丝袜情趣国产精品| 国产裸体美女永久免费无遮挡| 亚洲欧洲www| 成人免费无码大片a毛片| 老色鬼精品视频在线观看播放| a级免费在线观看| 成人精品亚洲| 国产精品久久国产精品99gif| 三级国产在线观看| 91精品国产全国免费观看| 日韩精品一区二区三| 不卡av免费在线观看| 国产aaa免费视频| 成人影视亚洲图片在线| 国产精品手机在线| 国产嫩草在线视频| www.午夜精品| 国产又粗又猛又黄又爽| 精品magnet| 男人的天堂久久久| 欧美国产精品专区| 亚洲综合欧美激情| 99热精品在线| 老司机激情视频| 日韩欧美字幕| 日本欧美色综合网站免费| 日本精品另类| 色婷婷av一区二区三区久久| 亚洲人成色777777精品音频| 日韩小视频在线观看专区| 中文无码av一区二区三区| 国产精品黄色在线观看| 不卡一区二区在线观看| 日韩中文字幕区一区有砖一区 | 日韩一区精品视频| 国产乱子伦农村叉叉叉| 九九免费精品视频在线观看| 成人一区二区在线| 国产午夜亚洲精品一级在线| 欧美国产中文字幕| 色婷婷激情五月| 日韩精品在线看片z| 国偷自拍第113页| 欧美国产乱子伦| 91久久免费视频| 91香蕉视频在线| 欧美成人午夜精品免费| 95精品视频在线| 天天干天天av| 黑人一区二区| 成人在线视频一区二区三区| 小小影院久久| 六月婷婷久久| 亚洲精品毛片| 欧美另类暴力丝袜| 好吊日视频在线观看| 日韩成人xxxx| 中文区中文字幕免费看| 欧美性高清videossexo| 久久综合久久鬼| 国产欧美日韩视频在线观看| 91av在线免费| 国产视频一区在线观看| 国产又黄又粗视频| 国产精品美女久久久久aⅴ| 国产精品综合激情| 一区二区三区自拍| 精品无码黑人又粗又大又长| 亚洲成国产人片在线观看| 美国美女黄色片| 91麻豆国产在线观看| 日本一区二区三区网站| 国产色婷婷亚洲99精品小说| www.涩涩爱| 亚洲卡通欧美制服中文| 国产无遮挡aaa片爽爽| 亚洲欧洲精品一区二区三区| 9999热视频| 性做久久久久久免费观看| 黄色在线视频网址| 欧美日韩国产高清一区| www.国产三级| 欧美日韩成人在线一区| 国产丝袜在线视频| 亚洲黄色www| 天天综合视频在线观看| 亚洲欧美在线看| 免费观看国产视频| 亚洲欧洲国产精品| √新版天堂资源在线资源| 欧美老少配视频| 在线能看的av网址| 成人午夜小视频| 国语自产精品视频在线看抢先版结局| 成人自拍性视频| 狼人精品一区二区三区在线| 日本在线观看一区二区| 中文字幕乱码亚洲无线精品一区| 欧美精品久久久久久久免费| 欧美日韩亚洲国产精品| 国产乱子夫妻xx黑人xyx真爽| 日韩视频精品在线观看| 中文久久久久久| 成人免费高清视频| 精人妻一区二区三区| 国产精品一级片| 国产又粗又猛又爽视频| 2023国产精品| 麻豆精品一区二区三区视频| 日韩欧美中文字幕在线观看| 国产一级精品视频| 欧美剧情电影在线观看完整版免费励志电影 | 国产美女扒开尿口久久久| 欧美一区国产| 51国偷自产一区二区三区| 国产精品一区二区三区四区在线观看| 精品国产免费久久久久久尖叫| 国产欧美自拍一区| 亚洲精品日韩精品| 99久久99久久精品国产片果冰| 国产精品一线二线三线| 精品一区二区综合| 亚洲国产av一区| 婷婷成人综合网| 精品国产av 无码一区二区三区 | 一区二区三区四区视频精品免费| 精品一区二区无码| 日韩二区三区在线| 亚洲91av| 91在线视频一区| 精品三级国产| 亚洲女人毛片| 日韩极品在线观看| 波多野结衣办公室33分钟| 亚洲一级在线观看| 国产黄色一区二区| 欧美成人精品h版在线观看| 四虎精品在线观看| 亚洲三区四区| 美女国产一区二区| 色欲狠狠躁天天躁无码中文字幕 | 国产精品日韩欧美| 精品国产乱码久久久久久蜜坠欲下 | http;//www.99re视频| 91精品综合久久久久久久久久久 | 永久免费网站视频在线观看| 精品一区二区三区的国产在线播放| 五月天精品在线| 欧美优质美女网站| av在线三区| 成人黄色生活片| 午夜激情久久| 在线视频一二区| 亚洲一区二区精品视频| а√中文在线资源库| 欧美激情网友自拍| 天天综合网天天| 99九九电视剧免费观看| 欧美人成网站| 久草免费资源站| 五月天视频一区| 黄色影院在线播放| 国产精品嫩草影院久久久| 93在线视频精品免费观看| 午夜剧场在线免费观看| 亚洲人吸女人奶水| а√天堂资源在线| 欧美一区二区三区……| 国产精品亚洲欧美一级在线| 国产盗摄视频在线观看| 日韩影院精彩在线| jizzjizz日本少妇| 欧美一区2区视频在线观看| 丰满诱人av在线播放| 久久久久久久久久久久久9999| 91精品天堂福利在线观看| 亚洲成人手机在线观看| 亚洲一线二线三线久久久| 少妇人妻精品一区二区三区| 日本高清不卡的在线| 色喇叭免费久久综合网| 日本成人在线免费| 黑人巨大精品欧美一区二区免费| 国产在线观看黄| 亚洲综合小说区| 亚洲欧美日韩专区| 欧美日韩一区二区区别是什么| 亚洲妇女屁股眼交7| 欧美黄色小说| 亚洲一区中文字幕| 国产亚洲在线| 中国xxxx性xxxx产国| 色哟哟精品一区| 成人三级网址| 就去色蜜桃综合| 国产老妇另类xxxxx| 亚洲欧美综合自拍| 久久国产精品网站| 神马电影久久| 先锋资源在线视频| 亚洲精品视频在线看| 亚洲av激情无码专区在线播放| 国产精品久久电影观看| 在线成人h网| 少妇精品无码一区二区三区| 欧美视频一区二区| av今日在线| 黑人巨大国产9丨视频|