<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                8.4 工廠方法模式的擴展 工廠方法模式有很多擴展,而且與其他模式結合使用威力更大,下面將介紹4種擴展。 1. 縮小為簡單工廠模式 我們這樣考慮一個問題:一個模塊僅需要一個工廠類,沒有必要把它產生出來,使用靜態的方法就可以了,根據這一要求,我們把上例中的AbstarctHumanFactory修改一下,類圖如圖8-3所示。 ![](https://box.kancloud.cn/2016-08-14_57b003608002f.jpg) 圖8-3 簡單工廠模式類圖 我們在類圖中去掉了AbstractHumanFactory抽象類,同時把createHuman方法設置為靜態類型,簡化了類的創建過程,變更的源碼僅僅是HumanFactory和NvWa類,HumanFactory如代碼清單8-13所示。 代碼清單8-13 簡單工廠模式中的工廠類 public?class?HumanFactory?{ ?????public?static?<T?extends?Human>?T?createHuman(Class<T>?c){ ?????????????//定義一個生產出的人種 ?????????????Human?human=null;?????????? ?????????????try?{ ?????????????????????//產生一個人種 ????????????????????human?=?(Human)Class.forName(c.getName()).newInstance();???? ?????????????}?catch?(Exception?e)?{ ????????????????????System.out.println("人種生成錯誤!"); ?????????????} ????????????return?(T)human; ?????} } HumanFactory類僅有兩個地方發生變化:去掉繼承抽象類,并在createHuman前增加static關鍵字;工廠類發生變化,也同時引起了調用者NvWa的變化,如代碼清單8-14示。 代碼清單8-14 簡單工廠模式中的場景類 public?class?NvWa?{ ?????public?static?void?main(String[]?args)?{??????????? ?????????????//女媧第一次造人,火候不足,于是白色人種產生了 ?????????????System.out.println("--造出的第一批人是白色人種--"); ?????????????Human?whiteHuman?=?HumanFactory.createHuman(WhiteHuman.class); ?????????????whiteHuman.getColor(); ?????????????whiteHuman.talk();????????? ?????????????//女媧第二次造人,火候過足,于是黑色人種產生了 ?????????????System.out.println("\n--造出的第二批人是黑色人種--"); ?????????????Human?blackHuman?=?HumanFactory.createHuman(BlackHuman.class); ?????????????blackHuman.getColor(); ?????????????blackHuman.talk();????????? ?????????????//第三次造人,火候剛剛好,于是黃色人種產生了 ?????????????System.out.println("\n--造出的第三批人是黃色人種--"); ?????????????Human?yellowHuman?=?HumanFactory.createHuman(YellowHuman.class); ?????????????yellowHuman.getColor(); ?????????????yellowHuman.talk(); ?????} } 運行結果沒有發生變化,但是我們的類圖變簡單了,而且調用者也比較簡單,該模式是工廠方法模式的弱化,因為簡單,所以稱為簡單工廠模式(Simple Factory Pattern),也叫做靜態工廠模式。在實際項目中,采用該方法的案例還是比較多的,其缺點是工廠類的擴展比較困難,不符合開閉原則,但它仍然是一個非常實用的設計模式。 2. 升級為多個工廠類 當我們在做一個比較復雜的項目時,經常會遇到初始化一個對象很耗費精力的情況,所有的產品類都放到一個工廠方法中進行初始化會使代碼結構不清晰。例如,一個產品類有5個具體實現,每個實現類的初始化(不僅僅是new,初始化包括new一個對象,并對對象設置一定的初始值)方法都不相同,如果寫在一個工廠方法中,勢必會導致該方法巨大無比,那該怎么辦? 考慮到需要結構清晰,我們就為每個產品定義一個創造者,然后由調用者自己去選擇與哪個工廠方法關聯。我們還是以女媧造人為例,每個人種都有一個固定的八卦爐,分別造出黑色人種、白色人種、黃色人種,修改后的類圖如圖8-4所示。 ![](https://box.kancloud.cn/2016-08-14_57b00360975fe.jpg) 圖8-4 多個工廠類的類圖 每個人種(具體的產品類)都對應了一個創建者,每個創建者都獨立負責創建對應的產品對象,非常符合單一職責原則,按照這種模式我們來看看代碼變化。 多工廠模式的抽象工廠類如代碼清單8-15所示。 代碼清單8-15 多工廠模式的抽象工廠類 public?abstract?class?AbstractHumanFactory?{ ?????public?abstract?Human?createHuman(); } 注意 抽象方法中已經不再需要傳遞相關參數了,因為每一個具體的工廠都已經非常明確自己的職責:創建自己負責的產品類對象。 黑色人種的創建工廠如代碼清單8-16所示。 代碼清單8-16 黑色人種的創建工廠實現 public?class?BlackHumanFactory?extends?AbstractHumanFactory?{ ?????public?Human?createHuman()?{ ?????????????return?new?BlackHuman(); ?????} } 黃色人種的創建工廠如代碼清單8-17所示。 代碼清單8-17 黃色人種的創建類 public?class?YellowHumanFactory?extends?AbstractHumanFactory?{ ?????public?Human?createHuman()?{ ?????????????return?new?YellowHuman(); ?????} } 白色人種的創建工廠如代碼清單8-18所示。 代碼清單8-18 白色人種的創建類 public?class?whiteHumanFactory?extends?AbstractHumanFactory?{ ?????public?Human?createHuman()?{ ?????????????return?new?WhiteHuman(); ?????} } 三個具體的創建工廠都非常簡單,但是,如果一個系統比較復雜時工廠類也會相應地變復雜。場景類NvWa修改后的代碼如代碼清單8-19所示。 代碼清單8-19 場景類NvWa public?class?NvWa?{ ?????public?static?void?main(String[]?args)?{??????????? ?????????????//女媧第一次造人,火候不足,于是白色人種產生了 ?????????????System.out.println("--造出的第一批人是白色人種--"); ?????????????Human?whiteHuman?=?(new?WhiteHumanFactory()).createHuman(); ?????????????whiteHuman.getColor(); ?????????????whiteHuman.talk();????????? ?????????????//女媧第二次造人,火候過足,于是黑色人種產生了 ?????????????System.out.println("\n--造出的第二批人是黑色人種--"); ?????????????Human?blackHuman?=?(new?BlackHumanFactory()).createHuman(); ?????????????blackHuman.getColor(); ?????????????blackHuman.talk();????????? ?????????????//第三次造人,火候剛剛好,于是黃色人種產生了 ?????????????System.out.println("\n--造出的第三批人是黃色人種--"); ?????????????Human?yellowHuman?=?(new?YellowHumanFactory()).createHuman(); ?????????????yellowHuman.getColor(); ?????????????yellowHuman.talk();???????????????????????? ?????} } 運行結果還是相同。我們回顧一下,每一個產品類都對應了一個創建類,好處就是創建類的職責清晰,而且結構簡單,但是給可擴展性和可維護性帶來了一定的影響。為什么這么說呢?如果要擴展一個產品類,就需要建立一個相應的工廠類,這樣就增加了擴展的難度。因為工廠類和產品類的數量相同,維護時需要考慮兩個對象之間的關系。 當然,在復雜的應用中一般采用多工廠的方法,然后再增加一個協調類,避免調用者與各個子工廠交流,協調類的作用是封裝子工廠類,對高層模塊提供統一的訪問接口。 3. 替代單例模式 第7章講述了單例模式以及擴展出的多例模式,并且指出了單例和多例的一些缺點,我們是不是可以采用工廠方法模式實現單例模式的功能呢?單例模式的核心要求就是在內存中只有一個對象,通過工廠方法模式也可以只在內存中生產一個對象,類圖如圖8-5所示。 ![](https://box.kancloud.cn/2016-08-14_57b00360af394.jpg) 圖8-5 工廠方法模式替代單例模式類圖 非常簡單的類圖,Singleton定義了一個private的無參構造函數,目的是不允許通過new的方式創建一個對象,如代碼清單8-20所示。 代碼清單8-20 單例類 public?class?Singleton?{??? ?????//不允許通過new產生一個對象 ?????private?Singleton(){ ?????} ?????public?void?doSomething(){ ?????????????//業務處理 ?????} } Singleton保證不能通過正常的渠道建立一個對象,那SingletonFactory如何建立一個單例對象呢?答案是通過反射方式創建,如代碼清單8-21所示。 代碼清單8-21 負責生成單例的工廠類 public?class?SingletonFactory?{ ?????private?static?Singleton?singleton; ?????static{? ?????????????try?{ ????????????????????Class?cl=?Class.forName(Singleton.class.getName()); ????????????????????//獲得無參構造 ????????????????????Constructor?constructor=cl.getDeclaredConstructor(); ????????????????????//設置無參構造是可訪問的 ????????????????????constructor.setAccessible(true); ????????????????????//產生一個實例對象 ????????????????????singleton?=?(Singleton)constructor.newInstance(); ?????????????}?catch?(Exception?e)?{ ????????????????????//異常處理 ?????????????} ?????} ?????public?static?Singleton?getSingleton(){ ?????????????return?singleton;?? ?????} } 通過獲得類構造器,然后設置訪問權限,生成一個對象,然后提供外部訪問,保證內存中的對象唯一。當然,其他類也可以通過反射的方式建立一個單例對象,確實如此,但是一個項目或團隊是有章程和規范的,何況已經提供了一個獲得單例對象的方法,為什么還要重新創建一個新對象呢?除非是有人作惡。 以上通過工廠方法模式創建了一個單例對象,該框架可以繼續擴展,在一個項目中可以產生一個單例構造器,所有需要產生單例的類都遵循一定的規則(構造方法是private),然后通過擴展該框架,只要輸入一個類型就可以獲得唯一的一個實例。 4. 延遲初始化 何為延遲初始化(Lazy initialization)?一個對象被消費完畢后,并不立刻釋放,工廠類保持其初始狀態,等待再次被使用。延遲初始化是工廠方法模式的一個擴展應用,其通用類圖如圖8-6所示。 ![](https://box.kancloud.cn/2016-08-14_57b00360c3e14.jpg) 圖8-6 延遲初始化的通用類圖 ProductFactory負責產品類對象的創建工作,并且通過prMap變量產生一個緩存,對需要再次被重用的對象保留,Product和ConcreteProduct是一個示例代碼,請參考代碼清單8-8和代碼清單8-9。ProductFactory如代碼清單8-22所示。 代碼清單8-22 延遲加載的工廠類 public?class?ProductFactory?{ ?????private?static?final?Map<String,Product>?prMap?=?new?HashMap(); ?????public?static?synchronized??Product?createProduct(String?type)?throws?Exception{ ?????????????Product?product?=null;????????????? ?????????????//如果Map中已經有這個對象 ?????????????if(prMap.containsKey(type)){ ????????????????????product?=?prMap.get(type); ?????????????}else{ ????????????????????if(type.equals("Product1")){ ????????????????????????????product?=?new?ConcreteProduct1(); ????????????????????}else{ ????????????????????????????product?=?new?ConcreteProduct2(); ????????????????????} ????????????????????//同時把對象放到緩存容器中 ????????????????????prMap.put(type,product); ?????????????} ?????????????return?product; ?????} } 代碼還比較簡單,通過定義一個Map容器,容納所有產生的對象,如果在Map容器中已經有的對象,則直接取出返回;如果沒有,則根據需要的類型產生一個對象并放入到Map容器中,以方便下次調用。 延遲加載框架是可以擴展的,例如限制某一個產品類的最大實例化數量,可以通過判斷Map中已有的對象數量來實現,這樣的處理是非常有意義的,例如JDBC連接數據庫,都會要求設置一個MaxConnections最大連接數量,該數量就是內存中最大實例化的數量。 延遲加載還可以用在對象初始化比較復雜的情況下,例如硬件訪問,涉及多方面的交互,則可以通過延遲加載降低對象的產生和銷毀帶來的復雜性。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看