目录
Hello,你好呀,我是灰小猿!一个超会写bug的程序猿!
工厂模式相信很多小伙伴们都有听说过,但是工厂模式在Java中的具体使用你有了解过吗?今天在这里和大家讲一下在Spring中如何使用三种工厂模式(静态工厂、实例工厂、自定义工厂)来创建bean对象并使用。
在这里我们先来讨论一下何为“工厂模式”,使用工厂模式的好处。
一、工厂模式介绍
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。
使用意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时使用。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行。
应用实例: 比如说你需要一辆汽车,你可以直接从工厂里面提货就可以了,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。这就是工厂模式。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
以上就是工厂模式的基本介绍和使用场景,那么到底应该如何在Java中实现工厂模式呢?下面我将通过在Spring中对bean进行实例化的例子来和大家详细分析一下三种工厂模式的具体使用。首先做一个准备工作,我们创建一个bean类AirPlane(飞机类),并实现属性的get和set方法;
package com.spring.beans; /** * 飞机类 * */ public class AirPlane { private String fdj;//飞机发动机 private String yc;//机翼长度 private String jzName;//机长名 private String fjzName;//副机长名 private Integer personNum;//乘客数 public String getFdj() { return fdj; } public void setFdj(String fdj) { this.fdj = fdj; } public String getYc() { return yc; } public void setYc(String yc) { this.yc = yc; } public String getJzName() { return jzName; } public void setJzName(String jzName) { this.jzName = jzName; } public String getFjzName() { return fjzName; } public void setFjzName(String fjzName) { this.fjzName = fjzName; } public Integer getPersonNum() { return personNum; } public void setPersonNum(Integer personNum) { this.personNum = personNum; } @Override public String toString() { return "AirPlane [fdj=" + fdj + ", yc=" + yc + ", jzName=" + jzName + ", fjzName=" + fjzName + ", personNum=" + personNum + "]"; } }
二、通过静态工厂方法创建Bean实例
在Spring中调用静态工厂方法创建bean是将对象创建的过程封装到静态方法中。当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节。
在IOC容器中,通过静态工厂方法声明创建bean的步骤是:
- 首先在bean的class属性里指定静态工厂类的全类名,
- 同时在factory-method属性里指定工厂方法的名称。
- 最后使用<constrctor-arg>元素为该方法传递方法参数。
接下来我们通过具体的代码来实现:
写一个静态工厂的实现类AirplaneStaticFactory,其中实现造飞机的静态方法getAirPlane(String jzName),传入一个参数代表机长姓名。并将创建的飞机对象返回。
package com.spring.factory; import com.spring.beans.AirPlane; /** * 飞机静态工厂 * */ public class AirplaneStaticFactory { /** * private String fdj;//飞机发动机 private String yc;//机翼长度 private String jzName;//机长名 private String fjzName;//副机长名 private Integer personNum;//乘客数 * */ public static AirPlane getAirPlane(String jzName) { AirPlane airPlane = new AirPlane(); airPlane.setFdj("太行"); airPlane.setYc("190.2"); airPlane.setJzName(jzName); airPlane.setFjzName("小刚"); airPlane.setPersonNum(300); return airPlane; } }
以上准备工作完成之后,就是通过静态工厂方法声明创建bean的实现了,按照上面的步骤在ioc容器中进行实现,
<!-- 通过静态工厂方法创建airplane实例 factory-method指定工厂方法名 --> <bean id="airplane01" class="com.spring.factory.AirplaneStaticFactory" factory-method="getAirPlane"> <!-- 为该方法传递方法参数--> <constructor-arg name="jzName" value="静态机长01"></constructor-arg> </bean>
之后通过ioc容器的getBean()方法就可以获取到创建的bean对象。测试如下:
//****************利用工厂方法来创建bean************* ApplicationContext iocContext4 = new ClassPathXmlApplicationContext("ioc4.xml"); /** * 利用工厂方法创建实例 * */ @Test public void test10() { // 利用静态工厂创建实例 AirPlane airPlane01 = (AirPlane)iocContext4.getBean("airplane01"); System.out.println(airPlane01); // 利用实例工厂创建实例 AirPlane airPlane02 = (AirPlane)iocContext4.getBean("airplane02"); System.out.println(airPlane02); // 利用自定义工厂创建实例 AirPlane airPlane03 = (AirPlane)iocContext4.getBean("myFactoryBean"); System.out.println(airPlane03); }
测试结果:
编辑
三、通过实例工厂方法创建Bean实例
实例工厂方法是将对象的创建过程封装到另外一个对象实例的方法里。当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节。
实例工厂的实现步骤是
- 配置工厂类实例的bean
- 在factory-method属性里指定该工厂方法的名称
- 使用 construtor-arg 元素为工厂方法传递方法参数
首先我们先写一个实现实例工厂的类AirplaneInstanceFactory,在其中实现创建bean对象的实例方法getAirPlane(String jzName),
package com.spring.factory; import com.spring.beans.AirPlane; /** * 飞机实例工厂 * */ public class AirplaneInstanceFactory { public AirPlane getAirPlane(String jzName) { AirPlane airPlane = new AirPlane(); airPlane.setFdj("太行"); airPlane.setYc("190.2"); airPlane.setJzName(jzName); airPlane.setFjzName("小刚"); airPlane.setPersonNum(300); return airPlane; } }
之后在IOC容器中配置实现工厂类的bean,指明是将哪一个实例工厂类实例化的。
<!-- 创建一个实例工厂 --> <bean id="airplaneInstanceFacatory" class="com.spring.factory.AirplaneInstanceFactory"></bean>
现在就是将bean对象进行实例化的过程了,在IOC容器中,我们创建一个bean实例,调用实例工厂中的工厂方法,来对bean进行实例化,在这里我们需要使用factory-method属性里指定该工厂方法的名称,同时使用 construtor-arg 元素为工厂方法传递方法参数。具体实现是这样的:
<!-- 创建一个bean实例,调用实例工厂中的工厂方法 --> <bean id="airplane02" class="com.spring.beans.AirPlane" factory-bean="airplaneInstanceFacatory" factory-method="getAirPlane" > <constructor-arg name="jzName" value="实例机长01"></constructor-arg> </bean>
现在通过实例工厂创建bean对象的过程就结束了,通过获取到ioc容器中的bean对象进行测试:
//****************利用工厂方法来创建bean************* ApplicationContext iocContext4 = new ClassPathXmlApplicationContext("ioc4.xml"); /** * 利用工厂方法创建实例 * */ @Test public void test10() { // 利用静态工厂创建实例 AirPlane airPlane01 = (AirPlane)iocContext4.getBean("airplane01"); System.out.println(airPlane01); // 利用实例工厂创建实例 AirPlane airPlane02 = (AirPlane)iocContext4.getBean("airplane02"); System.out.println(airPlane02); // 利用自定义工厂创建实例 AirPlane airPlane03 = (AirPlane)iocContext4.getBean("myFactoryBean"); System.out.println(airPlane03); }
测试结果:
编辑
四、通过自定义的factoryBean来创建bean对象
通过自定义的factoryBean来创建bean对象时,我们需要在工厂类上实现factoryBean接口,
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。
工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法所返回的对象。
工厂bean必须实现org.springframework.beans.factory.FactoryBean接口,使用factoryBean接口的一个好处就是只要是实现这个接口的类,spring都会认为是工厂。
该接口规定了三个方法:
编辑
我们先来创建一个自定义的、容器能够认识的factoryBean类,并且重写其中的三个方法。
package com.spring.factory; import org.springframework.beans.factory.FactoryBean; import com.spring.beans.AirPlane; import com.spring.beans.Book; /** * 创建一个实例工厂的接口 * 创建一个容器能够认识的factoryBean类, * 只要是这个接口实现的类,spring都会认为是工厂 * */ public class MyFactoryBeanImplements implements FactoryBean<AirPlane>{ /** * 工厂方法,返回创建的对象 * */ @Override public AirPlane getObject() throws Exception { // TODO Auto-generated method stub AirPlane airPlane = new AirPlane(); airPlane.setFdj("太行-2"); airPlane.setYc("290.2"); airPlane.setJzName("自定义机长01"); airPlane.setFjzName("小刚"); airPlane.setPersonNum(300); return airPlane; } /** * 返回对象的类型 * */ @Override public Class<?> getObjectType() { // TODO Auto-generated method stub return AirPlane.class; } /** * isSingleton 是单例吗? * false 不是单例 * true 是单例 * false和true是可以切换的 * */ @Override public boolean isSingleton() { // TODO Auto-generated method stub return false; } }
之后在IOC容器中直接对该自定义工厂类进行实例化,即可完成相应的bean的实例创建。
<!-- 通过自定义的factoryBean来创建对象 --> <!-- 该bean只有在调用时才会被创建,容器创建时不会创建该bean --> <bean id="myFactoryBean" class="com.spring.factory.MyFactoryBeanImplements" ></bean>
在使用该实例化的bean的时候,同样也是直接在IOC容器中获取相应的实例工厂即可。
//****************利用工厂方法来创建bean************* ApplicationContext iocContext4 = new ClassPathXmlApplicationContext("ioc4.xml"); /** * 利用工厂方法创建实例 * */ @Test public void test10() { // 利用静态工厂创建实例 AirPlane airPlane01 = (AirPlane)iocContext4.getBean("airplane01"); System.out.println(airPlane01); // 利用实例工厂创建实例 AirPlane airPlane02 = (AirPlane)iocContext4.getBean("airplane02"); System.out.println(airPlane02); // 利用自定义工厂创建实例 AirPlane airPlane03 = (AirPlane)iocContext4.getBean("myFactoryBean"); System.out.println(airPlane03); }
测试结果:
编辑
至此,在spring中使用三种工厂模式创建bean实例的过程就和大家讲完了,其中有不足的地方欢迎小伙伴们评论指正!
点赞关注,以留备用哟!
我是灰小猿,我们下期见!
编辑