意图: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方法的方式设置到对应的成员变量上。