意圖:java
簡單工廠模式是類的建立模式,又叫作靜態工廠方法(Static Factory Method)模式。簡單工廠模式是由一個工廠對象決定建立出哪種產品類的實例。一般它根據自變量的不一樣返回不一樣的類的實例。spring
適用性:app
簡單工廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該建立出哪個產品類的實例。ide
簡單工廠模式的構成:工具
下面創建一個Java Project來實現簡單工廠模式:ui
新建simplefactory項目,src下創建com.test.simplefactory包,首先是抽象產品角色,好比人,定義一個接口Person.java:this
package com.test.simplefactory; public interface Person { public String sayHello(String name); public String sayGoodbye(String name); }
下面定義中國人和美國人這樣兩個具體產品角色:編碼
定義一個實現了Person接口的Chinese類:xml
package com.test.simplefactory; public class Chinese implements Person { @Override public String sayGoodbye(String name) { return "再見, " + name; } @Override public String sayHello(String name) { return "你好, " + name; } }
而後是實現了Person接口的American類:對象
package com.test.simplefactory; public class American implements Person { @Override public String sayGoodbye(String name) { return "good bye, " + name; } @Override public String sayHello(String name) { return "hello, " + name; } }
按照之前的方式,在不使用工廠類的狀況下,咱們編寫客戶端Client類以下:
package com.test.simplefactory; public class Client { public static void main(String[] args) { Person chinese = new Chinese(); System.out.println(chinese.sayHello("張三")); System.out.println(chinese.sayGoodbye("張三")); Person american = new American(); System.out.println(american.sayHello("Tom")); System.out.println(american.sayGoodbye("Tom")); } }
運行Client.java,輸出以下:
你好, 張三 再見, 張三 hello, Tom good bye, Tom
下面,咱們來分析一下這個程序有哪些不足的地方:客戶端與具體實現類強耦合在一塊兒,具體實現類增長、刪除、修改了,客戶端類都要隨之發生變化。下面咱們看看如何用工廠模式完成一樣的功能。
新建一個PersonFactory類:
package com.test.simplefactory; public class PersonFactory { public Person getPerson(String name) { if("american".equals(name)) { return new American(); } else if("chinese".equals(name)) { return new Chinese(); } else { return null; } } }
如此以來,客戶端Client就能夠這樣寫了:
package com.test.simplefactory; public class Client { public static void main(String[] args) { PersonFactory factory = new PersonFactory(); Person chinese = factory.getPerson("chinese"); System.out.println(chinese.sayHello("張三")); System.out.println(chinese.sayGoodbye("張三")); Person american = new American(); System.out.println(american.sayHello("Tom")); System.out.println(american.sayGoodbye("Tom")); } }
這樣作的話,咱們的客戶端已經和具體的實現類沒有強耦合這樣的關係了,徹底被工廠所掩蓋了。這就是Spring IoC(Inverse of Control,控制反轉)/DI(Dependency Injection,依賴注入)的基礎。
接下來,咱們用Spring重現這個過程:新建一個Java Project:命名爲Spring1。
MyEclipse一樣提供了對Spring的支持,src->MyEclipse->Add Spring Capabilities,選擇Spring version版本號爲Spring2.5,點擊Next,去掉Enable AOP Builder前的勾勾,點擊Finish。此時src包下便多了一個Spring相關的配置文件:applicationContext.xml。
在src下面新建包:com.test,將simplefactory下的American、Chinese、Person這三個類拷貝到其下。接下來咱們利用Spring做爲工廠,實現相應的功能。
在applicationContext.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="chinese" class="com.test.Chinese"></bean> <bean id="american" class="com.test.American"></bean> </beans>
而後新建一個Client類:
package com.test; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; public class Client { public static void main(String[] args) { ClassPathResource cpr = new ClassPathResource("applicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory(cpr); Person chinese = (Person)factory.getBean("chinese"); System.out.println(chinese.sayHello("張三")); System.out.println(chinese.sayGoodbye("張三")); } }
運行能夠獲得和以前simplefactory項目相同的結果,這樣咱們就經過Spring實現了控制反轉(IoC/DI)。
如今對Spring咱們能夠說有了一些初步的認識,接下來咱們看一些更復雜的例子,看看Spring爲咱們提供了哪些強大的功能。
如前步驟,新建Java項目Spring2,新建com.test包。下面咱們常識使用Spring提供的依賴注入:對象依賴的其餘屬性由Spring自動幫咱們生成好。
在該包下面創建接口類Person:
package com.test; public interface Person { public void work(); }
人工做須要藉助工具來完成,所以咱們寫一個接口類Tool:
package com.test; public interface Tool { public void realWork(); }
下面是工具的兩個實現類ConcreteToolA和ConcreteToolB:
package com.test; public class ConcreteToolA implements Tool { @Override public void realWork() { System.out.println("realwork from ConcreteToolA"); } } ---------------------------------------------------------------------------------------------- package com.test; public class ConcreteToolB implements Tool { @Override public void realWork() { System.out.println("realwork from ConcreteToolB"); } }
而後是實現了Person類的Chinese類:
package com.test; public class Chinese implements Person { private Tool tool; public void setTool(Tool tool) { this.tool = tool; } public Tool getTool() { return tool; } @Override public void work() { tool.realWork(); } }
若是不借助Spring的話Client編碼以下:
package com.test; public class Client { public static void main(String[] args) { Chinese chinese = new Chinese(); Tool tool = new ConcreteToolA(); // Tool tool = new ConcreteToolB(); chinese.setTool(tool); chinese.work(); } }
客戶端與人和工具耦合,給咱們帶來了許多不便之處。接下來咱們看看如何用Spring把這些耦合通通給去除掉。
在applicationContext.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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="toolA" class="com.test.ConcreteToolA"></bean> <bean id="toolB" class="com.test.ConcreteToolB"></bean> <bean id="chinese" class="com.test.Chinese"> <property name="tool" ref="toolA"></property> </bean> </beans>
客戶端Client:
package com.test; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; public class Client { public static void main(String[] args) { ClassPathResource cpr = new ClassPathResource("applicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory(cpr); Person p = (Person)factory.getBean("chinese"); p.work(); } }
照樣可以獲得輸出:real work from ConcreteToolA。
MyEclipse操做補充:當配置文件很大的時候,如何快速瀏覽bean之間的依賴關係:Window->Show View->Spring Explorer。在列出的Spring項目中的applicationContext.xml上點擊右鍵->Open Graph。便可以圖形化的形式瀏覽各個bean之間的關係,好比Spring2項目下的bean之間的依賴關係:
補充:對於Spring2項目來講,就像Struts的Action同樣,對於每個屬性咱們要爲其提供對應的get和set方法,對於Spring來講,若是一個類裏面有屬性,那麼咱們至少要爲這個屬性提供一個set方法,讓Spring根據配置文件中指定的依賴關係經過調用set方法的方式設置到對應的成員變量上。