工厂模式
工厂模式简单的说就是为屏蔽对象的实例化过程
工厂模式可以分为三种
1. 简单工厂
2. 工厂方法模式
3. 抽象工厂模式
简单工厂模式
简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。如果不使用简单工厂模式,我们一般按如下的方法开发
以用户买车为例
抽象类车,他可以有很多子类比如大众,BMW或者奥迪
@ToString
public abstract class AbstractCar {
@Getter
protected String name="汽车";
public AbstractCar() {
}
}
目前用户只有很少的钱只够买一辆大众,那么代码如下
AbstractCar car = new DaZhong();
System.out.println("用户购买了一辆" + car.getName());
如果过段时间车价下降,原本买大众的钱可以买奥迪了,那么我们又得修改源代码
AbstractCar car = new AoDi();
System.out.println("用户购买了一辆" + car.getName());
我们可以通过简单工厂模式来避免上面的问题
具体的工厂类和工厂方法
public class SimpleFactory {
public static AbstractCar getCar(int price) {
if (price < 1000) {
return new DaZhong();
} else if (price < 2000) {
return new AoDi();
} else {
return new BMW();
}
}
}
调用工厂方法只需要传入金额就可以
public void simpleFactory() {
AbstractCar car = SimpleFactory.getCar(700);
System.out.println(car);
}
简单工厂模式有以下优点
1. 使代码结构清晰,有效封装变化,调用者无需关注产品的实例化过程
2. 向调用者屏蔽具体的产品类
工厂方法模式
简单工厂模式仍然存在以下的问题,车型有数千中,每年又有先增车型,如果将所有车型对象实例化放在工厂中的话,简单工厂会非常臃肿,同时对于新增车型也不利于扩展
工厂方法模式可以比较好的解决这个问题,比如奥迪车厂新增了某款车型,那么只需要修改奥迪车厂就可以
工厂方法模式包含如下几种角色
1.抽象工厂角色:
这是工厂方法模式的核心,与调用者交互提供具体的产品
2.工厂实现
工厂决定实例化产品的具体逻辑
3.产品接口
定义产品的规范,产品所拥有的功能,属性
4.产品实现
实现产品规范,实现具体的产品方法
抽象工厂
案例:
这一次用户有了明确的选择就是要买一辆奥迪
首先定义工厂接口
public interface CarFactory {
public AbstractCar createCar(int price);
}
具体的奥迪工厂的实现类
public class AoDiCarFactory implements CarFactory {
@Override
public AbstractCar createCar(int price) {
if (price < 1000) {
return new A4();
} else if (price < 1500) {
return new A7();
} else {
return new A8();
}
}
}
具体的用户调用过程如下
//首先选择具体的车厂
CarFactory aodiFactory=new AoDiCarFactory();
//付钱收车
AbstractCar car=aodiFactory.createCar(1000);
System.out.println(car);
Spring与工厂模式
Spring对工厂模式的支持包括两种,一种是静态工厂方法另一种是非静态工厂方法
静态工厂
public class StaticFlyInterface {
public static Fly getInstance() {
//返回某个接口实现类
return new Fighter();
}
}
在spring.xml配置文件中如下配置
<bean id="fly" class="com.spring.ioc.factory.staticfactory.StaticFlyInterface" factory-method="getInstance"/>
通过factory-method告知Spring通过StaticFlyInterface工厂类的getInstance方法构造Fly接口对象
fly接口的使用类如下
public class FlyUser {
//需要注入一个fly接口实现类
private Fly fly;
public void fly() {
System.out.println("I am going to fly");
fly.fly();
}
public Fly getFly() {
return fly;
}
public void setFly(Fly fly) {
this.fly = fly;
}
}
spring.xml声明
<bean id="flyUser" class="com.spring.ioc.factory.staticfactory.FlyUser">
<property name="fly" ref="fly"/>
</bean>
这里引用的fly对象就是通过工厂返回的对象
非静态工厂方法
public class NonStaticFactory {
public Fly getInstance() {
return new Fighter();
}
}
因为方法是非静态的所以我们得声明工厂实例,并通过调用工厂实例的非静态方法获取接口实现类
<!--声明的工厂实例-->
<bean id="flyFactory" class="com.spring.ioc.factory.staticfactory.NonStaticFactory"/>
<!--调用工厂方法获取接口实现类-->
<bean id="fly2" factory-bean="flyFactory" factory-method="getInstance"/>
FactoryBean
Spring还有一种特殊的bean也可以实现工厂模式
我们使用FactoryBean重复实现的功能
public class FlyFactoryBean implements FactoryBean<Fly> {
@Override
public Fly getObject() throws Exception {
return new Fighter();
}
@Override
public Class<?> getObjectType() {
return Fly.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
isSingleton()方法告诉容器,FlyFactoryBean对象生产的对象是否以singleton形式存在于容器中
Spring.xml配置
<!--配置FactoryBean-->
<bean id="flyFactoryBean" class="com.spring.ioc.container.FlyFactoryBean"/>
<!--
flyFactoryBean引用的FactoryBean并不是FactoryBean本身而是该FactoryBean所产生的对象
-->
<bean id="flyUser" class="com.spring.ioc.factory.staticfactory.FlyUser">
<property name="fly" ref="flyFactoryBean"/>
</bean>
如果我们一定要取得flyFactoryBean而不是它产生的对象,我们可以在这样获取
在FactoryBean id前加上&
Object o=context.getBean("&flyFactoryBean");
Spring框架内部也大量使用了FactoryBean接口比如
- JndiObjectFactoryBean
- LocalSessionFactoryBean
- SqlMapClientFactoryBean
- ProxyFactoryBean
- TransactionProxyFactoryBean