欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

简单工厂模式(Simple Factory Pattern)_Java

程序员文章站 2022-05-17 14:45:59
...

Simple Factory Pattern

简单工厂模式(Simple Factory Pattern)

 

工厂是什么呢?工厂是生产产品的,BeanFactory是生产Bean对象的,水果工厂是生产水果的,工厂模式的作用就是,我们不需要去new一个对象了,直接通过工厂模式,让工厂给我们提供需要的对象即可。

下面以水果工厂为例,简单说一下

 

package com.pattern.simplefactory;
/**
 * 水果工厂,用来造水果的,给我名字,我给你对象
 */
public class FruitFactory {

	public static Fruit getFruit(String name){
		if(name!=null&&name.equalsIgnoreCase("apple")){
			return new Apple();//匹配字符串,创建水果对象
		}
		return null;
	}
}

 

package com.pattern.simplefactory;
/**
 * 水果接口,所有的水果都有一个方法,sayName
 */
public interface Fruit {
	public void sayName();
}

 

package com.pattern.simplefactory;
/**
 * 苹果,实现了水果接口,有sayName方法
 */
public class Apple implements Fruit{

	@Override
	public void sayName() {
		System.out.println("Apple");
	}

}

 

package com.pattern.simplefactory;

public class Test {

	public static void main(String[] args) {
		Apple apple=(Apple) FruitFactory.getFruit("apple");
		apple.sayName();
	}
}

Spring里面的bean管理原理

Spring有一个工厂模式BeanFactory,提供一个getBean(name)方法
配置Spring的配置文件
applicationContext.xml
<bean name class/>
name对应的是获取class中完全限定名指定的类
用户通过getBean方法,传入name,获取指定的对象

bean管理的简单实现

 这里采用的是properties配置文件
prop.properties

apple=com.pattern.beanfactory.Apple

 

package com.pattern.beanfactory;

import java.io.IOException;
import java.util.Properties;

public class BeanFactory {
	//一次性读取src目录下的配置文件prop.properties存到prop中,Spring使用的是xml基本一样
	private static Properties prop;
	static{
		prop=new Properties();
		try {
			prop.load(BeanFactory.class.getClassLoader().getResourceAsStream("prop.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	//通过反射机制,返回指定name对应的class的实例
	public static Object getBean(String name){
		if(prop.containsKey(name)){
			String className=prop.getProperty(name);
			try {
				return Class.forName(className).newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}
}

 

package com.pattern.beanfactory;
/**
 * 水果接口,所有的水果都有一个方法,sayName
 */
public interface Fruit {
	public void sayName();
}

 

package com.pattern.beanfactory;
/**
 * 苹果,实现了水果接口,有sayName方法
 */
public class Apple implements Fruit{

	@Override
	public void sayName() {
		System.out.println("Apple");
	}

}

 

package com.pattern.beanfactory;

public class Test {
	public static void main(String[] args) {
		Apple apple=(Apple) BeanFactory.getBean("apple");
		apple.sayName();
	}
}

 

 

提醒:这是Spring的基本实现,但Spring的实例创建都是单例模式

如何让我们的的BeanFactory提供的实例是单例模式呢?

 prop1.properties
apple=com.pattern.beanfactory1.Apple

package com.pattern.beanfactory1;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class BeanFactory {
	private static Properties prop;
	//map集合中用来装实例,保证一个name只对应一份实例
	private static Map<String, Object> map=new HashMap<String, Object>();
	static{
		prop=new Properties();
		try {
			prop.load(BeanFactory.class.getClassLoader().getResourceAsStream("prop1.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	//通过反射机制,返回指定name对应的class的实例
	public static Object getBean(String name){
		if(prop.containsKey(name)){
			//如果map中存在实例,直接返回,如果不存在,执行创建过程,并将新的实例添加到map中,下次getBean就不用newInstance了
			if(map.containsKey(name)){
				return map.get(name);
			} else{
				String className=prop.getProperty(name);
				try {
					Object o=Class.forName(className).newInstance();
					map.put(name, o);
					return o;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

 

package com.pattern.beanfactory1;
/**
 * 水果接口,所有的水果都有一个方法,sayName
 */
public interface Fruit {
	public void sayName();
}

 

package com.pattern.beanfactory1;
/**
 * 苹果,实现了水果接口,有sayName方法
 */
public class Apple implements Fruit{

	@Override
	public void sayName() {
		System.out.println("Apple");
	}

}

 

package com.pattern.beanfactory1;

public class Test {
	public static void main(String[] args) {
		Apple apple=(Apple) BeanFactory.getBean("apple");
		Apple apple2=(Apple) BeanFactory.getBean("apple");
		System.out.println(apple==apple2);//true
	}
}

 

提醒:事实上,Spring在容器启动的时候就完成了配置的类的实例化,而不是用户需要的时候才去实例并单例的。


我们如何实现在容器启动的时候完成实例并单例呢?

其实很简单,把实例操作放到static静态块中即可!

只有BeanFactory中部分变化:

package com.pattern.beanfactory1;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

public class BeanFactory {
	private static Properties prop;
	//map集合中用来装实例,保证一个name只对应一份实例
	private static Map<String, Object> map=new HashMap<String, Object>();
	static{
		prop=new Properties();
		try {
			prop.load(BeanFactory.class.getClassLoader().getResourceAsStream("prop1.properties"));
			//*****************************************************
			//Spring的真正的单例形式,大致是这样的,在容器启动的时候就实例所有的配置类
			for(Entry<Object, Object> entry:prop.entrySet()){
				String key=entry.getKey().toString();
				String className=entry.getValue().toString();
				try {
					map.put(key, Class.forName(className).newInstance());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			//*****************************
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static Object getBean(String name){
		//获取实例,直接到map中去找即可
		if(map.containsKey(name)){
			return map.get(name);
		}
		return null;
	}
}

简单工厂模式是面试常考的题目,学完简单工厂模式,最大的收获应该是对Spring的BeanFactory有更深入的理解,并且对单例模式有了更深一层的认识!