精品欧美一区二区三区在线观看 _久久久久国色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)

天天操天天摸天天舔| 欧美污视频网站| 亚洲av综合色区无码一区爱av| 欧美视频一区| 亚洲另类图片色| 中文字幕第一页在线视频| av午夜在线观看| 国产三级一区二区三区| 91丨九色丨国产| 无码人妻熟妇av又粗又大| 91精品国产乱码久久久久久| 精品国产乱码久久久久久蜜臀| 久久精品午夜福利| 超碰免费公开在线| 久久久一区二区三区| 亚洲一区国产精品| 亚洲男人天堂网址| 国产一区观看| 日韩中文在线观看| 亚洲专区区免费| 国产精品高清一区二区| 91高清视频在线| 六月婷婷在线视频| 国产在线高潮| 中文av字幕一区| 久久国产精品一区二区三区| 国产精品无码久久av| 日韩中文字幕91| 98精品国产高清在线xxxx天堂| 国产中文字幕久久| 国内成人精品| 亚洲精品影视在线观看| 老司机午夜免费福利| 国产95亚洲| 欧美日韩视频第一区| 5月婷婷6月丁香| a'aaa级片在线观看| 亚洲免费观看高清完整版在线观看| 欧美一区国产一区| 后入内射欧美99二区视频| 国产在线精品一区二区不卡了| 国产精品电影观看| 7799精品视频天天看| 极品中文字幕一区| 欧美激情亚洲激情| 免费一级黄色大片| 国产精品草草| 欧美精品日韩三级| 农村黄色一级片| 全球成人免费直播| 中文字幕亚洲天堂| 欧日韩不卡视频| 欧美午夜精彩| 中文字幕亚洲精品| 波多野结衣在线网址| 97精品视频在线看| 久久天堂av综合合色| 美国美女黄色片| 日韩av自拍| 日韩午夜在线视频| 欧美视频一区二区在线| 久久久9色精品国产一区二区三区| 中文字幕亚洲精品| 青青青在线免费观看| 欧美精品1区| 欧美国产第一页| 五月天综合在线| 亚洲资源av| 日本一区二区在线播放| 中国一级特黄视频| 国产一区不卡在线| 国产精品二区在线| 手机福利小视频在线播放| 久久久五月婷婷| 日本一区二区三不卡| 中文字幕日本在线观看| 亚洲日本丝袜连裤袜办公室| www.日本在线视频| 一级毛片久久久| 欧美日韩在线播| 亚洲一区 二区 三区| 26uuu精品一区二区三区四区在线| 亚洲国产91色在线| 中文字幕乱码在线人视频| av成人资源| 亚洲精品色婷婷福利天堂| 最近中文字幕在线mv视频在线| 欧美特黄一级大片| 色综合天天狠天天透天天伊人| 精品少妇久久久| 久久国产精品亚洲77777| 国产精品欧美亚洲777777| 99产精品成人啪免费网站| 成人免费高清在线| 日本在线一区| 牛牛电影国产一区二区| 福利视频第一区| www.cao超碰| 日本欧美高清| 中文字幕日韩在线播放| 国产精品18p| 秋霞午夜av一区二区三区| 高清不卡一区二区三区| 国产在线观看黄| 一区二区国产盗摄色噜噜| 日本成年人网址| 国产精品国产三级在线观看| 亚洲精品在线91| 欧美精品久久久久性色| 日韩中文字幕区一区有砖一区 | 亚洲一区三区电影在线观看| 手机av免费在线| 色美美综合视频| 一级全黄裸体片| 成人免费在线播放| 欧美一区二区影院| av官网在线观看| 欧美激情综合在线| 欧洲黄色一级视频| 我要色综合中文字幕| 自拍偷拍亚洲区| 天码人妻一区二区三区在线看 | 中文乱码人妻一区二区三区视频| 日韩理论电影| 日本成人激情视频| 六月丁香色婷婷| 最新欧美精品一区二区三区| 成人免费观看视频在线观看| 欧美视频精品全部免费观看| 少妇久久久久久| 波多野结衣爱爱| 99在线热播精品免费| 99久re热视频精品98| 日本精品在线一区| 国产亚洲激情视频在线| 日本在线播放视频| 99久久精品国产一区| 国产 欧美 日韩 一区| 成人噜噜噜噜| 日韩视频在线免费| 91在线你懂的| 中文字幕欧美三区| 欧美伦理视频在线观看| 亚洲免费专区| 91av成人在线| 亚州av在线播放| 亚洲成人在线网站| 一级黄色电影片| 一区在线视频| 国产精品国产三级国产专区53| 亚洲电影视频在线| 精品日韩欧美一区二区| 国产亚洲欧美精品久久久www| 国产成人免费高清| 性高湖久久久久久久久aaaaa| 视频精品一区| 欧美精品videos| 日本精品一区二区在线观看| 亚洲一区二区欧美| 老熟妇精品一区二区三区| 亚洲国产黄色| 美女视频久久| 欧美va在线观看| 日韩在线播放视频| 99精品免费观看| 亚洲综合免费观看高清完整版在线| 26uuu国产| 亚洲看片免费| 欧美污视频久久久| 青青在线精品| 欧美xxxx18性欧美| 欧美一区二区黄片| 色悠悠久久综合| 美女av免费看| 国产高清视频一区| 成人一对一视频| 国内精品久久久久久99蜜桃| 国产一区二中文字幕在线看| 在线看一级片| 亚洲国产免费av| 三级网站在线播放| 亚洲图片你懂的| 亚洲天堂2024| 日韩vs国产vs欧美| 特级西西444| 亚洲婷婷影院| 亚洲综合中文字幕68页| 999福利在线视频| 在线看日韩欧美| www.日韩在线观看| 欧美色视频日本高清在线观看| 日韩视频在线观看免费视频| 国产一区二区三区在线看麻豆| 欧美一二三不卡| 国产精品一国产精品| 91嫩草免费看| 欧美aaa视频| 欧美高清激情视频| 国产高清视频在线播放| 日韩精品一区二区三区swag| 精品久久久久久久久久久久久久久久| 中文字幕亚洲区| 疯狂揉花蒂控制高潮h| 加勒比av一区二区| 黄色片视频在线播放| 欧美大片一区| 神马影院我不卡| 久久超级碰碰| 亚洲a成v人在线观看| 日本成人伦理电影| 91国在线精品国内播放| 九义人在线观看完整免费版电视剧| 亚洲高清久久久久久| 国产一区二区三区中文字幕| 一道本成人在线| 久久成人国产精品入口| 国产精品麻豆欧美日韩ww| 中文文字幕文字幕高清| 国产裸体歌舞团一区二区| 密臀av一区二区三区| 亚洲激情网站| 成人在线免费观看视频网站| 日韩.com| 日本不卡一区二区三区在线观看| 99re91这里只有精品| 成人免费淫片aa视频免费| 日韩欧美另类一区二区| 91高清在线免费观看| 精精国产xxxx视频在线中文版| 日韩最新av在线| 成人好色电影| 亚洲欧美精品一区| 香蕉视频黄在线观看| 精品欧美一区二区三区精品久久| 91国内精品视频| 欧美色爱综合网| 五月婷婷丁香在线| 色婷婷精品大视频在线蜜桃视频 | 色国产综合视频| 国产 欧美 日韩 在线| 亚洲成人福利片| 免费在线视频一区二区| 亚洲欧美一区二区久久| 三级黄色录像视频| 国产精品人妖ts系列视频| 一级在线观看视频| 国产精品天天摸av网| 国产真人做爰视频免费| 欧美国产一区二区在线观看 | 亚洲激情第一区| 欧美第一页在线观看| 亚洲欧美经典视频| 欧美国产在线看| 亚洲五月六月丁香激情| 麻豆一区二区三区精品视频| 亚洲曰韩产成在线| 国产精彩视频在线| 欧美性猛交xxxx免费看漫画 | 久久精品二区三区| 色婷婷综合久久久久中文字幕 | 国产aaa精品| 日韩网站中文字幕| 成人精品久久av网站| 精品午夜视频| 国产福利久久精品| 婷婷激情久久| 亚洲成人午夜在线| 这里只有精品在线| 青春草国产视频| 美女日韩在线中文字幕| 中文字幕永久视频| 国产一本一道久久香蕉| 制服丝袜在线第一页| 久久综合五月天婷婷伊人| 黄色片网站免费| 综合av第一页| 国产精品999在线观看| 色偷偷88欧美精品久久久| 在线观看不卡的av| 欧美成人一区二区三区在线观看| 特黄视频在线观看| 一区二区三区精品99久久| 欧美a在线看| 久久男人资源视频| 日韩精品第一| 99国产超薄肉色丝袜交足的后果| 亚洲永久精品唐人导航网址| 亚洲欧洲精品一区| 在线看片一区| 精品999在线| 成人动漫一区二区三区| 欧美丰满老妇熟乱xxxxyyy| 亚洲色图在线看| 视频一区二区三区四区五区| 欧美区一区二区三区| 四季av日韩精品一区| www.午夜精品| 一个人www视频在线免费观看| 国产在线a不卡| 亚洲成在人线免费观看| 免费看av软件| 玖玖在线精品| 美女露出粉嫩尿囗让男人桶| 欧美国产日韩在线观看| 国产亚洲成人精品| 欧美撒尿777hd撒尿| 天天操天天射天天| 久久久精品国产| 永久免费毛片在线播放| 亚洲精品免费一区二区三区| 国产日产一区| 日本人体一区二区| 激情综合色丁香一区二区| 无码人妻精品一区二区中文| 亚洲自拍与偷拍| 国产又黄又猛又爽| 国产一区二区三区网站| 日韩电影免费看| 99精彩视频| 婷婷亚洲五月| 国产精品久久久毛片| 91美女视频网站| 国产乱码久久久久久| 日韩一二三四区| 精产国品自在线www| 国产精品老牛影院在线观看| 少妇久久久久| 九色自拍视频在线观看| 国产乱妇无码大片在线观看| 中国1级黄色片| 欧美在线free| 黄色大片在线看| 日本一区二区在线播放| 中国av一区| 国产成人无码一二三区视频| av电影在线观看一区| 久久久久久久久久久97| 91精品国产91久久综合桃花| 欧美成人二区| 成人免费在线网址| 亚洲v在线看| xxx中文字幕| 亚洲精品高清在线观看| 国产熟女一区二区三区五月婷| 欲色天天网综合久久| 日本精品在线中文字幕| 午夜午夜精品一区二区三区文| 日韩电影在线观看一区| 性欧美一区二区| 欧美四级电影在线观看| av在线资源网| 91精品国产自产在线| 久久久国产精品| 国产成人精品综合久久久久99| 亚洲免费av高清| 日本精品999| 日韩av大片在线| 欧美一区电影| 日本美女视频一区| 一区二区三区日韩在线观看| 人妻少妇精品无码专区| 2023亚洲男人天堂| 极品美女一区二区三区| 香蕉视频禁止18| 亚洲欧洲国产日韩| 亚洲a视频在线| 欧美性视频精品| 欧美亚洲国产激情| www.污网站| 亚洲高清久久久| 四虎精品在永久在线观看 | 亚洲无码精品在线播放| 久久久国产成人精品| 日韩在线精品强乱中文字幕| 久操网在线观看| 国产日韩欧美一区二区三区综合 | 精品国产一区二区三区久久久蜜月| 黄色在线看片| 欧美日韩精品免费看| 国模娜娜一区二区三区| 日韩av在线播放观看| 国产一区二区三区日韩欧美| 精品久久国产一区| 国产午夜福利视频在线观看| 国产精品久久久久久久久图文区| av网站在线免费看| 欧美在线www| 中文字幕人成人乱码| 超碰97在线资源站| 欧美乱妇23p| 美女在线视频免费| 在线观看国产一区| 91免费国产视频网站| 国产精品视频a| 日韩av手机在线看| 亚洲字幕久久| 日韩中文字幕有码| 精品成人一区二区三区四区| 天堂久久午夜av| 天堂…中文在线最新版在线|