参开资料:
Spring揭秘
设计模式之禅
先来看看Factory Method Pattern,我想搞一个工厂来生成一些bean
/*这是接口*/
public interface Person {
public void say();
}
/*这是两个实现类*/
public class WPerson implements Person {
@Override
public void say() {
System.out.println("白种人");
}
}
public class YPerson implements Person {
@Override
public void say() {
System.out.println("黄种人");
}
}
有了这两个实现类,现在我想我给出一个Class,、就有一个工厂生产这个Class对应的一个实例给我。
FactoryBean代码:
import com.factory.entity.Person;
public class MyFactoryBean {
public static Person getInstance(Class s) {
Person p = null;
try {
p = (Person)Class.forName(s.getName()).newInstance();
} catch (InstantiationException e){
System.out.println("没找到这个类");
} catch (IllegalAccessException e) {
System.out.println("Person自身定义有问题");
} catch (ClassNotFoundException e) {
System.out.println("没找到这个类");
}
return p;
}
}
然后这个FactoryBean就可以干活了:
import com.factory.FactoryBean.MyFactoryBean;
import com.factory.entity.Person;
import com.factory.entity.WPerson;
import com.factory.entity.YPerson;
public class TestMain {
public static void main(String ai[]) {
Person p = MyFactoryBean.getInstance(WPerson.class);
Person p1 = MyFactoryBean.getInstance(YPerson.class);
p.say();
p1.say();
}
}
运行结果:
Factory Method Pattern先说这些,
下面我们来看看Spring中用到这个模式的地方:
有时候,我们会用到第三方的类库,需要实例化相关的类,这时,可以用Factory Method Pattern来避免借口与实现类的耦合性。提供一个工厂类来实例化具体的借口实现类,这样主体对象只需要依赖工厂类,如果实现类有变更,主体对象就不需要做任何变动。
例如:
public class A {
private Person p;
public A() {
//p = new WPerson();
/*应避免这样做,改用一下方式*/
//p = MyFactoryBean.getInstance();
}
}
当需求改变,不需要白人,而需要黄种人的时候,就可以只改MyFactoryBean的getInstance(),而不需要修改A类的原代码。
,如果用上配置文件看上去就更方便了:
import com.factory.entity.Person;
public class TestService {
private Person p;
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
}
/*为了方便,可以把MyFactotyBean的getInstance()方法稍作修改*/
public class MyFactoryBean {
public static Person getInstance(String personName) {
//把方法参数改成String类型的方便传值。
Person p = null;
try {
p = (Person)Class.forName(personName).newInstance();
} catch (InstantiationException e){
System.out.println("没找到这个类");
} catch (IllegalAccessException e) {
System.out.println("Person自身定义有问题");
} catch (ClassNotFoundException e) {
System.out.println("没找到这个类");
}
return p;
}
}
<!-- 配置Factory
指定factory-method之后,Factory就会返回该方法的返回值,而不是返回一个Factory的实例
通过constructor-arg可以指定factory-method方法的参数,用法跟普通的用法一样。如果没有该方法没有参数也可以不加,就直接使用factory-method就行了。
-->
<bean id="myFactory" class="com.factory.FactoryBean.MyFactoryBean" factory-method="getInstance" >
<constructor-arg name="personName" value="com.factory.entity.WPerson" />
</bean>
<bean id="test" class="com.test.TestService">
<property name="p">
<ref bean="myFactory" />
<!--此处得到的就不是myFactory的实例,而是factory-method返回的类型-->
</property>
</bean>
测试类:
public class TestMain {
public static void main(String ai[]) {
ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationcontext.xml");
TestService t = (TestService)ac.getBean("test");
t.getP().say();
}
}
测试结果:
这是静态工厂方法,使用的factory-method是一个静态方法,
如果将getInstance()的static关键字去掉,程序会报错:
也可以使用非静态的工厂方法,其他不变,只需要修改配置文件。
<!-- 配置Factory -->
<!-- 先生成一个Factory,再使用 -->
<bean id="myFactoryImp" class="com.factory.FactoryBean.MyFactoryBean" />
<bean id="myFactory" factory-bean="myFactoryImp" factory-method="getInstance">
<constructor-arg name="personName" value="com.factory.entity.WPerson" />
</bean>
然后现在如果要修改成黄种人,就只需改很少的配置文件就行了。
现在我们再来看看 Spring中的FactoryBean
FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口。更BeanFactory有着本质的区别,BeanFactory是Sopring的一种容器类型,还有一种是ApplicationContext。
这是Spring中FactoryBean的源码,
1.getObject()方法返回该FactoryBean生产的对象实例,
2.getObjectType()返回,getObject()方法生产出来的对象实例的类型。如果预选无法确定就返回null
3.isSingleton(),生成的对象实例是否要以singleton的形式存在于容器中,
提供这个接口当然就可以自己实现,
import org.springframework.beans.factory.FactoryBean;
import com.factory.entity.Person;
public class MyFactoryBean2 implements FactoryBean {
private String personName;
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
@Override
public Object getObject() throws Exception {
Person p = null;
try {
p = (Person)Class.forName(personName).newInstance();
} catch (InstantiationException e){
System.out.println("没找到这个类");
} catch (IllegalAccessException e) {
System.out.println("Person自身定义有问题");
} catch (ClassNotFoundException e) {
System.out.println("没找到这个类");
}
return p;
}
@Override
public Class getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
/*设置true单例模式,设置false每次都生成一个*/
return true;
}
}
配置文件:
<bean id="test" class="com.test.TestService" scope="prototype">
<property name="p">
<ref bean="myFactory" />
</property>
</bean>
<bean id="myFactory" class="com.factory.FactoryBean.MyFactoryBean2">
<property name="personName" value="com.factory.entity.YPerson" />
</bean>
测试类:
public class TestMain {
public static void main(String ai[]) {
ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationcontext.xml");
TestService t = (TestService)ac.getBean("test");
t.getP().say();
TestService t1 = (TestService)ac.getBean("test");
System.out.println(t + "\n" + t1);
System.out.println(t.getP() + "\n" + t1.getP());
}
}
运行结果:
关于FactoryBean就说这么多。
下面来看看
Factory Method Pattern(工厂方法模式)
继续更新。。