<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          工廠方法模式:在 Spring Boot 中的典型應(yīng)用

          共 5318字,需瀏覽 11分鐘

           ·

          2022-02-20 19:56

          大家好,我是CodingLong!

          在上一篇《簡單工廠模式》中我們了解到,簡單工廠模式每次增加新的產(chǎn)品時,都要修改其“工廠類”,這違背了開閉原則。而本篇介紹的工廠方法模式,對“工廠類”進一步抽象,即使新增產(chǎn)品也不用修改原來的代碼,這滿足了開閉原則。

          1 定義

          工廠方法模式(Factory Method Pattern)定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。

          Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

          也就是說,我們需要提供一個抽象的工廠接口,聲明一個創(chuàng)建對象的工廠方法,由其子類具體實現(xiàn)工廠方法,并決定創(chuàng)建哪一個產(chǎn)品對象。

          2 角色

          下面是工廠方法模式中的幾個角色:

          • 抽象產(chǎn)品(Product):所有具體產(chǎn)品的公共接口。
          • 具體產(chǎn)品(ConcreteProduct):實現(xiàn)了Product接口,是工廠方法中創(chuàng)建的對象。
          • 抽象工廠(Factory):所有具體工廠的公共接口。聲明一個工廠方法,該方法返回一個Product類型的對象。
          • 具體工廠(ConcreteFactory):實現(xiàn)了Factory接口,工廠方法返回一個ConcreteProduct實例。
          • 客戶端(Client):客戶端通過具體工廠來創(chuàng)建對應(yīng)的產(chǎn)品實例。

          下面是該模式的UML類圖:

          3 實現(xiàn)

          還是以《簡單工廠模式》中的手機案例,來講解該模式的實現(xiàn)。

          3.1 抽象產(chǎn)品接口:Phone

          創(chuàng)建一個手機接口,它可以打電話和發(fā)短信。

          /**
          ?*?手機接口
          ?*/

          public?interface?Phone?{

          ????/**
          ?????*?打電話
          ?????*/

          ????void?call();

          ????/**
          ?????*?發(fā)短信
          ?????*/

          ????void?sendSMS();
          }

          3.2 兩個具體產(chǎn)品類:XiaomiPhone和RedmiPhone

          為手機接口創(chuàng)建兩個實現(xiàn)類,一個是小米手機,一個是紅米手機,當然也可以有更多的實現(xiàn)類。

          /**
          ?*?小米手機實現(xiàn)類
          ?*/

          public?class?XiaomiPhone?implements?Phone?{
          ????@Override
          ????public?void?call()?{
          ????????System.out.println("使用小米手機打電話");
          ????}

          ????@Override
          ????public?void?sendSMS()?{
          ????????System.out.println("使用小米手機發(fā)短信");
          ????}
          }

          /**
          ?*?紅米手機實現(xiàn)類
          ?*/

          public?class?RedmiPhone?implements?Phone?{
          ????@Override
          ????public?void?call()?{
          ????????System.out.println("使用紅米手機打電話");
          ????}

          ????@Override
          ????public?void?sendSMS()?{
          ????????System.out.println("使用紅米手機發(fā)短信");
          ????}
          }

          3.3 一個工廠接口:PhoneFactory

          創(chuàng)建一個手機工廠的接口,包含一個創(chuàng)建Phone的方法。

          /**
          ?*?手機工廠接口
          ?*/

          public?interface?PhoneFactory?{
          ????/**
          ?????*?獲取手機實例
          ?????*
          ?????*?@return
          ?????*/

          ????Phone?createPhone();
          }

          3.4 兩個具體工廠類:XiaomiPhoneFactory和RedmiPhoneFactory

          創(chuàng)建兩個具體手機工廠實現(xiàn)類,每個工廠創(chuàng)建各自的產(chǎn)品實例。

          /**
          ?*?小米手機工廠類
          ?*/

          public?class?XiaomiPhoneFactory?implements?PhoneFactory?{
          ????@Override
          ????public?Phone?createPhone()?{
          ????????return?new?XiaomiPhone();
          ????}
          }

          /**
          ?*?紅米手機工廠類
          ?*/

          public?class?RedmiPhoneFactory?implements?PhoneFactory?{
          ????@Override
          ????public?Phone?createPhone()?{
          ????????return?new?RedmiPhone();
          ????}
          }

          3.5 客戶端:Client

          創(chuàng)建一個客戶端,通過XiaomiPhoneFactory工廠創(chuàng)建小米手機;通過RedmiPhoneFactory工廠創(chuàng)建紅米手機。

          /**
          ?*?客戶端類
          ?*/

          public?class?Client?{

          ??public?static?void?main(String[]?args)?{
          ????????System.out.println("================小米手機================");
          ????????Phone?xiaomiPhone?=?new?XiaomiPhoneFactory().createPhone();
          ????????xiaomiPhone.call();
          ????????xiaomiPhone.sendSMS();

          ????????System.out.println("================紅米手機================");
          ????????Phone?redmiPhone?=?new?RedmiPhoneFactory().createPhone();
          ????????redmiPhone.call();
          ????????redmiPhone.sendSMS();
          ????}
          }

          3.6 運行結(jié)果

          運行客戶端main方法,會打印如下內(nèi)容:

          ================小米手機================
          使用小米手機打電話
          使用小米手機發(fā)短信
          ================紅米手機================
          使用紅米手機打電話
          使用紅米手機發(fā)短信

          4 優(yōu)缺點

          優(yōu)點:

          • 使對象的創(chuàng)建和使用分離,對象的創(chuàng)建交給具體的工廠類負責,客戶端不需要關(guān)心是怎么創(chuàng)建的,只關(guān)心如何使用就行了。
          • 一個具體工廠只負責創(chuàng)建一個產(chǎn)品實例,遵循了單一職責。
          • 新增產(chǎn)品時,只需創(chuàng)建一個對應(yīng)的工廠類即可,遵循了開閉原則。

          缺點:

          • 每增加一個產(chǎn)品,都要增加一個對應(yīng)的工廠類,類的數(shù)量激增。

          5 典型應(yīng)用

          我們以Redis連接為例,來看下工廠方法模式在Spring Boot中的應(yīng)用。

          在Java中,連接Redis的兩個比較常用的客戶端是JedisLettuce,它們都被Spring官方加入到了spring-data-redis項目中,使用戶可以自由的選擇使用哪種連接方式。

          來看下它的整體結(jié)構(gòu):

          RedisConnection是Redis連接接口,在工廠方法模式中屬于抽象產(chǎn)品角色。它有兩個主要實現(xiàn)類:JedisConnectionLettuceConnection,是工廠方法中創(chuàng)建的具體產(chǎn)品。

          RedisConnectionFactory是Redis連接工廠接口,在工廠方法模式中屬于抽象工廠角色。它有兩個實現(xiàn)類:JedisConnectionFactoryLettuceConnectionFactory

          JedisConnectionFactory工廠中創(chuàng)建的是JedisConnection對象:

          public?class?JedisConnectionFactory?implements?InitializingBean,?DisposableBean,?RedisConnectionFactory?{
          ??????//...
          ??????
          ??????/*
          ???????*?獲取Redis連接
          ???????*/

          ??????public?RedisConnection?getConnection()?{
          ????
          ????????assertInitialized();
          ????
          ????????if?(isRedisClusterAware())?{
          ??????????return?getClusterConnection();
          ????????}
          ????
          ????????Jedis?jedis?=?fetchJedisConnector();
          ????????JedisClientConfig?sentinelConfig?=?this.clientConfig;
          ????
          ????????SentinelConfiguration?sentinelConfiguration?=?getSentinelConfiguration();
          ????????if?(sentinelConfiguration?!=?null)?{
          ??????????sentinelConfig?=?createSentinelClientConfig(sentinelConfiguration);
          ????????}
          ????
          ????????JedisConnection?connection?=?(getUsePool()???new?JedisConnection(jedis,?pool,?this.clientConfig,?sentinelConfig)
          ????????????:?new?JedisConnection(jedis,?null,?this.clientConfig,?sentinelConfig));
          ????????connection.setConvertPipelineAndTxResults(convertPipelineAndTxResults);
          ????????return?postProcessConnection(connection);
          ??????}
          ??????
          ??????//...
          }

          而在LettuceConnectionFactory工廠中創(chuàng)建的是LettuceConnection對象:

          public?class?LettuceConnectionFactory
          ????implements?InitializingBean,?DisposableBean,?RedisConnectionFactory,?ReactiveRedisConnectionFactory?
          {
          ??????//?...

          ??????/*
          ???????*?獲取Redis連接
          ???????*/

          ??????public?RedisConnection?getConnection()?{
          ????
          ????????assertInitialized();
          ????
          ????????if?(isClusterAware())?{
          ??????????return?getClusterConnection();
          ????????}
          ????
          ????????LettuceConnection?connection;
          ????????connection?=?doCreateLettuceConnection(getSharedConnection(),?connectionProvider,?getTimeout(),?getDatabase());
          ????????connection.setConvertPipelineAndTxResults(convertPipelineAndTxResults);
          ????????return?connection;
          ??????}
          ??????
          ??????//?...
          ?
          }

          6 完整代碼

          完整代碼請訪問我的Github,若對你有幫助,歡迎給個?,感謝~~??????

          https://github.com/gozhuyinglong/blog-demos/blob/main/design-patterns/src/main/java/io/github/gozhuyinglong/designpatterns/factory/FactoryMethod.java

          7 推薦閱讀

          微信搜索:碼農(nóng)StayUp

          主頁地址:https://gozhuyinglong.github.io

          源碼分享:https://github.com/gozhuyinglong/blog-demos


          瀏覽 198
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一区二区三区色欲 | 少妇三区 | 九一精品 | 高清无码在线免费视频 | 靠逼视频免费的 |