从基础知识到重写Spring的Bean工厂中学习java的工厂模式

时间:2022-09-27 19:43:33

1、静态工厂模式
其他对象不能直接通过new得到某个类,而是通过调用getInstance()方法得到该类的对象
这样,就可以控制类的产生过程。
顺带提一下单例模式和多例模式:
  单例模式是指控制其他对象获得该对象永远只有同一个对象
  而多例模式则是根据需要从某个具体集合中获取所需的对象

 import java.util.ArrayList;
import java.util.List; public class Car implements Moveable{
private static Car car = new Car(); //控制其他对象获得该对象永远只有同一个对象
private static List<Car> cars = new ArrayList<Car>(); //多例 //将构造方法私有化,限制其他对象无限制的new出Car对象
private Car(){} //通过静态方法获得new 出的对象
//即在取得该对象的过程由Car本身控制,可以为其添加各类限制
public static Car getInstance(){
//if() if。。。。
return car;
}
public void run(){
System.out.println("the car is running......");
}
}

2、普通工厂模式
与静态工厂不同,普通工厂将产生的过程交由其他的类处理,而并非类的本身。

 public class CarFactory {

     @Override
Moveable create() {
return new Car() ;
}
}

这样就可以通过获得CarFactory的对象,调用create()得到Car对象

3、抽象工厂模式

抽象工厂是指工厂类要产生一个系列的对象,将工厂类进行抽象,这样就可以通过改变工厂类,从而能够改变一系列的对象。
其实這就慢慢接近面向抽象编程。

这里类就比较多,就从抽象程度由上到下进行介绍:
(1)、测试类

 public class Test {
public static void main(String[] args){ AbstractFactory d = new DefaultFactory(); /**
可以通过AbstractFactory d = new NewFactory() 可以替换系类对象
**/ Vehicle v = d.createVehicle();
Food f = d.createFood(); v.run();
f.eat(); }
}

(2)、抽象工厂

 public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Food createFood();
}

(3)、抽线工厂实现类

 public class NewFactory extends AbstractFactory{

     @Override
public Vehicle createVehicle() {
return new Plane();
} @Override
public Food createFood() {
return new Banana();
}
}
 public class DefaultFactory extends AbstractFactory{

     @Override
public Vehicle createVehicle() {
return new Car();
} @Override
public Food createFood() {
return new Apple();
}
}

(4)、交通工具抽象类以及实现类

 public abstract class Vehicle {
public abstract void run();
}

******************************

 public class Car extends Vehicle{

     public void run(){
System.out.println("the car is running......");
}
}
 public class Plane extends Vehicle{
@Override
public void run() {
System.out.println("the plane is flying...");
}
}

(5)、食物抽象类以及实现类

 public abstract class Food {
public abstract void eat();
}

*****************************

 public class Apple extends Food{
public void eat(){
System.out.println("eating apple...");
}
}
 public class Banana extends Food{
public void eat(){
System.out.println("eating Banana...");
}
}

普通工厂模式与抽象工厂各有优缺点,
在产生对象系类时,普通工厂会有工厂泛滥的现象
抽象工厂在产生新的对象类型时,从上到下都需要改动

4、Spring的Bean工厂
现在就需要运用工厂知识来模拟Spring的Bean工厂了

我们先看看Spring是如何运用Bean工厂的

(1)、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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="v" class="com.csu.springFactory.Train">
</bean>
<!--类似 一般配置文件的 v="com.csu.springFactory.Car" 的格式--> </beans>

(2)、测试类:

 import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestForSpring {
public static void main(String[] args){
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Object o = factory.getBean("v"); //找到 id = v对应的class, getInstance得到一个Bean对象,返回
Moveable m = (Moveable)o;
m.run(); }
}

Spring 的applicationContext.xml中配置了实体类的信息,通过解析改配置文件,可以得到一个包含了所有类对象的工厂,
然后其他对象通过该工厂对象,调用getBean得到,以id为参数,得到对象

在理解了这些之后,我们就可以开始模拟了,其实最主要的部分就是在于解析xml配置文件,可以通过id获得类名,然后利用
反射得到该类,getInstance()后获得对象。解析xml文件有很对方法,这里就用JDOM.

(1)模拟的配置文件 applicationContext_simulation.xml (简化)

<?xml version="1.0" encoding="UTF-8"?>
<beans> <bean id="v" class="com.csu.springSimulation.Car">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!--类似 spring.properties配置文件的 v="com.csu.springFactory.Car" 的格式--> </beans>

(2)模拟BeanFactory

public interface BeanFactory_simulation { Object getBean(String id); }

(3)模拟BeanFactory的实现类ClassPathXmlApplicationContext_simulation

 import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import java.util.HashMap;
import java.util.List;
import java.util.Map; public class ClassPathXmlApplicationContext_simulation implements BeanFactory_simulation{
//要自定义方法解析applicationContext.xml
//Spring 的解析方式为ClassPathXmlApplicationContext("applicationContext.xml"); 这个类就是要模拟ClassPathXmlApplicationContext的功能 private Map<String,Object> container = new HashMap<String, Object>(); //存放所有对象 public ClassPathXmlApplicationContext_simulation(String filename) throws Exception {
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream(filename));
Element root=doc.getRootElement();
List list=root.getChildren("bean"); System.out.println(list.size()); for(int i=0;i<list.size();i++){
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id");
String clazz = element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance();
container.put(id,o); } } @Override
public Object getBean(String id) {
return container.get(id);
}
}

(4)测试类

 public class Test {
public static void main(String[] args) throws Exception {
BeanFactory_simulation beanFactory_simulation = new ClassPathXmlApplicationContext_simulation("com/csu/springSimulation/applicationContext_simulation.xml");
Object o = beanFactory_simulation.getBean("v");
Moveable m = (Moveable)o;
m.run();
}
}

这样我们就基本清楚了Spring的Bean工厂的模式了,面向抽象编程,将具体类放在配置文件中。