一、工廠方法模式中的三種模式的特點
工廠模式中的三種模式,分別是:簡單工廠模式、工廠方法模式、抽象工廠模式,三種分別是什么,以及適合場景是什么?
(1)簡單工廠模式:一個抽象接口對應一個產品接口,特定產品實現這個接口,針對不同產品都可以在同一個工廠中生產,同一個工廠生產產品可以通過多種方式,單生產方法(通過類型判定具體是要哪個產品,並進行new返回),多生產方法(工廠中有多個產品的不同生產方法,每一個生產方法對應一個new 產品的return),或者是靜態方法簡單工廠(將工廠中的返回某個產品的方法類設置為static,則直接通過類調用靜態方法即可,不需要new工廠類的對象實例)
該方法的問題是:如果要新增一個產品,必須對工廠類進行修改,但是如果通過反射或者其他方式可以做統一處理,其實也不會涉及到這個問題,如果要新增一個產品必須要對工廠類修改的時候,此時針對簡單工廠模式的修改覺得比較麻煩的話或者想要使擴展性更好的話,可以通過工廠方法模式(備注:簡單工廠模式比較像一個集中廠,各種不同的東西都能產)
Client端去調用的時候,需要知道:工廠的類名,及提供的生產方法從而可以獲得具體產品的實例,以及產品的接口,可以通過實例調用接口得到需要的產品的信息
其實就是:一個工廠類名Fatory,從工廠的生產方法獲取具體產品實例,getProduct()其中會返回new ProductA()或者new ProductB(),之后想要真正去進行產品的使用,還需要通過產品的接口,進行調用,例如ProductA.getProductInfo()等
(2)工廠方法模式:可以看做是簡單工廠模式的升級版;工廠方法模式就是一個工廠接口和多個工廠實現類,要增加一個新的產品,增加一個新的工廠實現類即可,針對之前的老的工廠實現類也不需要修改
工廠方法模式相當於在簡單工廠模式的基礎上,增加了對於不同的產品進行多個不同工廠的實現類的添加,不同的工廠用於Get不同的產品,用於進行不同產品的具體生產
Client進行調用的時候,直接通過識別不同工廠,然后通過工廠接口類提供的公共方法,即可進行接口方法調用,獲取產品;還需要知道具體的產品接口,用於進行具體的產品信息的獲取
(3)抽象工廠模式:針對有多個接口的情況,應用於有多個產品族產生的情況
抽象工廠模式中可以定義不止一個接口,一個工廠也可以生產不止一個產品類,但是即使是這樣,如果要新增一個新的接口,在其中需要修改的部分也是很多的,抽象工廠類的接口需要增加,其他工廠對於該類型的產品的工廠實現要增加,同時可以通過新建其他產品類進行具體產品類的返回;但是如果針對某一個接口對應的產品門類的話,是可以很方便的添加的,而且對老的工廠接口和具體的工廠類,都沒有影響,也就是說我想要建一個新的工廠,進行產品的生產,很容易。
二、Spring中的工廠方式模式的使用FactoryBean
FactoryBean是一個接口,具體包含的接口如下所以:
這三個接口具體含義是:
T getObject() throws Exception; //返回此工廠管理的對象的實例 Class<?> getObjectType(); //返回此FactoryBean創建的對象的類型 //這個工廠返回的對象是否是單例,默認返回true;若是單例則由getObject返回的//是相同的對象,是可以緩存的引用 default boolean isSingleton() { return true; }
基於此,我們知道這個FactoryBean也用於生成對象實例,那么其實也是一種Bean,該類型的Bean可以作為對通過xml或者普通的注解直接進行生成Bean的一種補充,簡單的說就是:可以通過FactoryBean來返回你想要的Bean,該類的Bean的生成可能是會比較復雜,或者你想要在做一些擴展操作的,都可以使用該方式
后面,可以重點說明一下ProxyFactoryBean,這個部分會在代理模式的時候說明~
下面通過對FactoryBean的實現,看一下自己使用的效果,FactoryBean的代碼如下:
package factorybean.demo; /** * Created by xiami on 2019/6/3. */ public interface FactoryBean <T> { T getObject(); Class<?> getObjectType(); default boolean isSingleton(){return true;} }
下面是User類對FactoryBean的實現:
package factorybean.demo; /** * Created by xiami on 2019/6/3. */ public class User implements FactoryBean { private String name; private String passWd; private int age; public void setAge(int age) { this.age = age; } public void setPassWd(String passWd) { this.passWd = passWd; } public void setName(String name) { this.name = name; } @Override public Object getObject() { if (age <= 0){ return new Exception("年齡輸入錯誤"); } else { return "輸入參數正確"; } } @Override public Class<?> getObjectType() { return User.class; } public String getName() { return name; } public String getPassWd() { return passWd; } public int getAge() { return age; } }
重點關注:在getObject()中針對輸入的不同age參數做了一個判斷,用於輸出參數是否異常
接下來是:
在springtest.xml文件中進行配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="factorybeanUser" class="factorybean.demo.User"> <property name="name" value="lxlx" /> <property name="passWd" value="111" /> <property name="age" value="1"/> </bean> </beans>
注意,因為在簡單工廠模式中實現的GetBean還無法解析FactoryBean的類型,因此這里直接用的Spring-Framework作為lib庫方便對Spring中的xml解析和GetBean的調用,Client調用類代碼如下:
package factorybean.demo; import org.springframework.beans.BeansException; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by 58 on 2019/6/3. */ public class Client { public static void main(String[] args) throws BeansException { ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:factorybean/demo/springtest.xml"); User user = (User)classPathXmlApplicationContext.getBean("factorybeanUser"); System.out.println(user.getObject()); } }
當springtest.xml中配置age的值為-1時,運行結果為:
當springtest.xml中配置age的值為12時,運行結果為:
可見:通過對FactoryBean的接口的實現,在getObject()中能夠返回自己想要的內容,通過GetBean()就可以獲取到,之后的文章會對FactoryBean在GetBean中是什么時候被獲取做介紹
參考文章:
https://blog.csdn.net/zknxx/article/details/79572387