抽象工厂模式在spring源码中的应用
創建型模式
目錄
1、抽象工廠模式
1.1 抽象工廠的UML類圖
1.2 日常生活中看抽象工廠模式
1.3 具體例子
2、抽象工廠模式在spring源碼中的應用
3、抽象工廠優缺點
3.1 優點
3.2 缺點
3.3 使用場景
1、抽象工廠模式
抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產品的具體的情況下,創建多個產品族中的產品對象。
在抽象工廠中最明顯的一個特點是產品不止一類了,在抽象工廠在提到一個“產品族”的概念。
1.1 抽象工廠的UML類圖
1.2 日常生活中看抽象工廠模式
就好像東方紅拖拉機廠在工廠方法模式下只能生產拖拉機,但是在抽象工廠模式下不僅能生產拖拉機,還能生產卡車(如果加一個坦克的生產線,還能生產坦克)。
1.3 具體例子
我們現在有這么一個場景;現在用戶的需求變多了,除了要求不同的形狀之外,我們還要求創建不同顏色的形狀,比如圓形,我們要求紅色的圓形、赤橙黃綠青藍紫等各種各樣顏色的圓形。按照我們抽象方法模式的設計方案,那么我們就需要實現各種顏色的形狀并實現這些顏色的形狀對應的工廠類,這樣一來我們系統中會增多非常多的工廠類。看起來如下:
//具體類的抽象接口 public interface Shape {//接口方法 } //具體類Circle public class Circle implements Shape {//接口方法實現 } //具體類紅色圓 public class RedCircle implements Shape {//接口方法實現 } //...各種顏色的圓... //具體類Triangle public class Triangle implements Shape { //接口方法實現 } //具體類紅色Triangle public class RedTriangle implements Shape { //接口方法實現 } //...各種顏色的Triangle... //工廠接口 public interface ShapeFactory {Shape getShape(); } //CircleFactory public class CircleFactory implements ShapeFactory {//返回實例 } //RedCircleFactory public class RedCircleFactory implements ShapeFactory {//返回實例 } //...各種顏色的Circle的工廠... //TriangleFactory public class TriangleFactory implements ShapeFactory {//返回實例 } //RedTriangleFactory public class RedTriangleFactory implements ShapeFactory {//返回實例 } //...各種顏色的Triangle的工廠...那么我們有沒有辦法對當前的設計方案進行優化,減少一些工廠類的產生呢?我們下面對當前的系統做進一步抽象。以形狀為類的級別、顏色為族來對當前系統作進一步改善。
首先我們要以形狀為等級、顏色為族來對系統進行進一步抽象。
等級抽象
進行等級抽象我們需要將不同的形狀聲明為抽象類(等級劃分)并實現公共的抽象接口(Shape),然后具體的實現類繼承自對應的抽象類;
//形狀公共接口 public interface Shape {void draw(); } //圓形抽象類Circle public abstract class Circle implements Shape {public abstract void draw(); } //長方形抽象類Rectange public abstract class Rectange implements Shape {public abstract void draw(); } //其他圖形抽象類... ...具體的實現類繼承自對應的抽象類,繼承自不同的抽象類就相當于將類劃分為不同的等級,如:
//具體顏色的Circle實現 public class BlueCircle extends Circle {@Overridepublic void draw() {System.out.println("繪制藍色的圓");} } public class RedCircle extends Circle {@Overridepublic void draw() {System.out.println("繪制紅色的圓");} }//具體顏色的Rectange實現 public class RedRectange extends Rectange{@Overridepublic void draw() {System.out.println("繪制紅色長方形");} } public class BlueRectange extends Rectange {@Overridepublic void draw() {System.out.println("繪制藍色長方形");} }具體類族抽象
具體類族的劃分我們以顏色為基礎,不同類族的對象我們通過對應的具體工廠來創建。所以首先我們需要定義一個抽象工廠,具體工廠(族)實現抽象工廠的方法來生成一組具體對象。
//抽象工廠ShapeFactory public interface ShapeFactory {Shape getCircle();Shape getRectange(); }//RedShapeFactory(他所代表的是紅色形狀這一族) public class RedShapeFactory implements ShapeFactory {@Overridepublic Shape getCircle() {return new RedCircle();}@Overridepublic Shape getRectange() {return new RedRectange();} }//BlueShapeFactory(他所代表的是蘭色形狀這一族) public class BlueShapeFactory implements ShapeFactory {@Overridepublic Shape getCircle() {return new BlueCircle();}@Overridepublic Shape getRectange() {return new BlueRectange();} }//...其他族...等級以及族類劃分完成之后,我么的客戶端在使用時只需要知道抽象工廠(ShapeFactory )以及具體工廠(如BlueShapeFactory )就可以獲得指定族的所有形狀。
public class TestDemo {public static void main(String[] args) {ShapeFactory redShapeFactory = new RedShapeFactory();Shape circle = redShapeFactory.getCircle();circle.draw();Shape rectangle = redShapeFactory.getRectange();rectangle.draw();ShapeFactory greenShapeFactory = new GreenShapeFactory();Shape greenCircle = greenShapeFactory.getCircle();greenCircle.draw();} }從上面的例子我們就可以知道,抽象工廠模式為創建一組對象提供了一種解決方案。 與工廠方法模式相比, 抽象工廠模式中的具體工廠不只是創建一種具體對象, 它負責創建一組(族)具體對象。
抽象工廠模式包含的角色
-
抽象工廠:聲明一組用于創建一族產品的方法,每個方法對應一種對象;在抽象工廠中聲明了多個工廠方法, 用于創建不同類型的對象, 抽象工廠可以是接口, 也可以是抽象類或者具體類,具體實現可參考上例中的ShapeFactory;
-
具體工廠:具體工廠實現了抽象工廠,每個工廠方法返回一個具體對象,一個具體工廠所創建的具體對象構成一個族。具體實現可參考上例中的RedShapeFactory;
-
抽象類接口:提供一組所有類都具有的業務方法。
-
抽象類:用于實現抽象接口所定義的業務方法,但是該角色對于抽象接口定義的方法只做抽象實現,即所有實現都被定義為抽象方法,最終的具體實現全部交給具體類實現。引入該角色主要是為了根據聲明不同的抽象類,將類區分為不同的等級結構。
-
具體類:該角色繼承抽象類,主要用于實現抽象類中聲明的抽象方法,完成不同等級結構,不同族的業務方法的具體實現。
根據我們上面對抽象工廠模式的描述,我們大致能夠明白,如果我們在上例的基礎上想要增加綠色或者其他顏色的圖形時,我們只需要增加一個綠色產品工廠(GreenShapeFactory),同時繼承不同的圖形抽象類實現不同顏色的圖形具體類即可,看起來如下:
//GreenShapeFactory public class GreenShapeFactory implements ShapeFactory {@Overridepublic Shape getCircle() {return new GreenCircle();}@Overridepublic Shape getRectange() {return new GreenRectange();}}//GreenRectange public class GreenRectange extends Rectange {@Overridepublic void draw() {System.out.println("繪制綠色長方形");} }//GreenCircle public class GreenCircle extends Circle{@Overridepublic void draw() {System.out.println("繪制綠色圓");} }我們增加這些拓展,并不會影響到原來的代碼,這看起來是符合“開閉原則”的;但是我們再深入思考一下,如果我們現在想增加一個新的圖形,比如說三角形(Triangle)。而對于我們目前所做的設計來講,我們將三角形(Triangle)放到任何一個等級機構(即繼承自任何一個圖形抽象類,如Circle)都顯得有些格格不入。但是我們如果在系統之中增加一個三角形(Triangle)的抽象類并實現不同顏色的三角形(Triangle)類之后我們會發現,我們需要修改所有的抽象工廠,這并不符合“開閉原則”。即在抽象工廠模式中,我們只能夠對族進行拓展,在對族進行拓展的情況下,時符合“開閉原則”的,如上例中增加不同顏色的指定圖形;但是對類的等級結構做拓展,是不符合“開閉原則”的;
因此使用抽象工廠模式要求設計人員在設計之初就能夠全面考慮, 不會在設計完成之后向系統中增加新的等級結構, 也不會刪除已有的等級結構, 否則將會導致系統出現較大的修改, 為后續維護工作帶來諸多麻煩。
2、抽象工廠模式在spring源碼中的應用
在 Spring 中,BeanFactory 是用于管理 Bean 的一個工廠,所有工廠都是 BeanFactory 的子類。這樣我們可以通過 IOC 容器來管理訪問 Bean,根據不同的策略調用 getBean() 方法,從而獲得具體對象。
其中,BeanFactory 接口的源碼如下:
public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";Object getBean(String name) throws BeansException;<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;boolean containsBean(String name);boolean isSingleton(String name) throws NoSuchBeanDefinitionException;boolean isPrototype(String name) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String name) throws NoSuchBeanDefinitionException;String[] getAliases(String name); }BeanFactory 的子類主要有 ClassPathXmlApplicationContext、XmlWebApplicationContext、StaticWebApplicationContext、StaticApplicationContext。在 Spring 中,DefaultListableBeanFactory 實現了所有工廠的公共邏輯。
3、抽象工廠優缺點
3.1 優點
-
抽象工廠模式隔離了具體類的生成, 使得客戶并不需要知道什么被創建。 由于這種隔離,更換一個具體工廠就變得相對容易, 所有的具體工廠都實現了抽象工廠中定義的那些公共接口, 因此只需改變具體工廠的實例, 就可以在某種程度上改變整個軟件系統的行為。
-
當一個族中的多個對象被設計成一起工作時, 它能夠保證客戶端始終只使用同一個族中的對象。
-
增加新的族很方便, 無須修改已有系統, 符合“開閉原則”。
3.2 缺點
- 增加新的等級結構麻煩, 需要對原有系統進行較大的修改, 甚至需要修改抽象層代碼,這顯然會帶來較大的不便, 違背了“開閉原則”。
3.3 使用場景
-
一個系統不應當依賴于具體類實例如何被創建、 組合和表達的細節, 這對于所有類型的工廠模式都是很重要的, 用戶無須關心對象的創建過程, 將對象的創建和使用解耦;
-
系統中有多于一個的族, 而每次只使用其中某一族。 可以通過配置文件等方式來使得用戶可以動態改變族, 也可以很方便地增加新的族。
-
屬于同一個族的對象將在一起使用, 這一約束必須在系統的設計中體現出來。 同一個族中的對象可以是沒有任何關系的對象, 但是它們都具有一些共同的約束, 如同一操作系統下的按鈕和文本框, 按鈕與文本框之間沒有直接關系, 但它們都是屬于某一操作系統的, 此時具有一個共同的約束條件: 操作系統的類型。
-
等級結構穩定, 設計完成之后, 不會向系統中增加新的等級結構或者刪除已有的等級結構。
?
參考文章:
https://blog.csdn.net/zyhlwzy/article/details/80707488
https://my.oschina.net/u/2003960/blog/532375
http://c.biancheng.net/view/8393.html
總結
以上是生活随笔為你收集整理的抽象工厂模式在spring源码中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 硬盘格式化了怎么恢复数据
- 下一篇: 计算机维修口诀,菜鸟必收藏:电脑故障维修