1.假如有多种产品,使用一个工厂来生产,使用者只与工厂联系在一起,该种方式称之为简单工厂模式。
2.下面摘抄一个简单的例子:(来源李刚的javaee实战)
例子比较简单,一个工厂类管理了俩个打印机(实际会更多);而使用者Computer只与工厂类耦合;
优势:让对象的调用者和对象创建过程分离,当对象调用者需要对象时,直接像工厂请求。从而避免了对象的调用者与对象的实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。
缺陷:当产品修改时,工厂类也要做相应修改;当产品非常多,一个工厂类显然管理会混乱。
public class Computer
{
private Output out;
private String name;
public Computer(){}
//out属性的setter和getter方法
public void setOut(Output out)
{
this.out = out;
}
//name属性的setter和getter方法
public void setName(String name)
{
this.name = name;
}
//定义一个模拟获取字符串输入的方法
public void keyIn(String msg)
{
out.getData(msg);
}
//定义一个模拟打印的方法
public void print()
{
System.out.println(name + "开始打印...");
out.out();
}
}
public interface Output
{
//接口里定义的属性只能是常量
int MAX_CACHE_LINE = 50;
//接口里定义的只能是public的抽象实例方法
void out();
void getData(String msg);
}
public class OutputFactory
{
public Output getOutput(String type)
{
//下面两行代码用于控制系统到底使用Output的哪个实现类。
if(type.equalsIgnoreCase("printer") {
return new Printer();
} else {
return new BetterPrinter();
}
}
}
public class Printer implements Output
{
private String[] printData = new String[MAX_CACHE_LINE];
//用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
//只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("打印机打印:" + printData[0]);
//把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE)
{
System.out.println("输出队列已满,添加失败");
}
else
{
//把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
}
}
public class BetterPrinter implements Output
{
private String[] printData = new String[MAX_CACHE_LINE * 2];
//用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
//只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("高速打印机正在打印:" + printData[0]);
//把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE * 2)
{
System.out.println("输出队列已满,添加失败");
}
else
{
//把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
}
}
3.下面是简单的模拟Spring IoC的容器的方式来生成对象:(来源李刚的javaee实战)
该容器仅仅实现了简单的IoC功能,可以创建并管理容器中所有的Bean实例。
<?xml version="1.0" encoding="GBK"?>
<beans>
<bean id="computer" class="Computer">
<!-- 为name属性注入普通属性值 -->
<property name="name" value="李刚的电脑"/>
<!-- 为out属性注入普通属性值 -->
<property name="out" ref="betterPrinter"/>
</bean>
<!-- 配置两个Bean实例 -->
<bean id="printer" class="Printer"/>
<bean id="betterPrinter" class="BetterPrinter"/>
<!-- 配置一个prototype行为的Bean实例 -->
<bean id="now" class="java.util.Date" scope="prototype"/> <!--①-->
</beans>
public interface ApplicationContext
{
//获取指定Bean实例的方法
Object getBean(String name)
throws Exception;
}
public class YeekuXmlApplicationContext
implements ApplicationContext
{
//保存容器中所有单例模式的Bean实例
private Map<String , Object> objPool
= Collections.synchronizedMap(new HashMap<String , Object>());
//保存配置文件对应的Document对象
private Document doc;
//保存配置文件里的根元素
private Element root;
public YeekuXmlApplicationContext(String filePath)
throws Exception
{
SAXReader reader = new SAXReader();
doc = reader.read(new File(filePath));
root = doc.getRootElement();
initPool();
initProp();
}
public Object getBean(String name)
throws Exception
{
Object target = objPool.get(name);
//对于singleton Bean,容器已经初始化了所有Bean实例
if (target.getClass() != String.class)
{
return target;
}
else
{
String clazz = (String)target;
//对于prototype并未注入属性值
return Class.forName(clazz).newInstance();
}
}
//初始化容器中所有singleton Bean
private void initPool()
throws Exception
{
//遍历配置文件里的每个<bean.../>元素
for (Object obj : root.elements())
{
Element beanEle = (Element)obj;
//取得<bean.../>元素的id属性
String beanId = beanEle.attributeValue("id");
//取得<bean.../>元素的class属性
String beanClazz = beanEle.attributeValue("class");
//取得<bean.../>元素的scope属性
String beanScope = beanEle.attributeValue("scope");
//如果<bean.../>元素的scope属性不存在,或为singleton
if (beanScope == null ||
beanScope.equals("singleton"))
{
//以默认构造器创建Bean实例,并将其放入objPool中
objPool.put(beanId , Class.forName(beanClazz).newInstance());
}
else
{
//对于非singlton Bean,存放该Bean实现类的类名。
objPool.put(beanId , beanClazz);
}
}
}
//初始化容器中singleton Bean的属性
private void initProp()
throws Exception
{
//遍历配置文件里的每个<bean.../>元素
for (Object obj : root.elements())
{
Element beanEle = (Element)obj;
//取得<bean.../>元素的id属性
String beanId = beanEle.attributeValue("id");
//取得<bean.../>元素的scope属性
String beanScope = beanEle.attributeValue("scope");
//如果<bean.../>元素的scope属性不存在,或为singleton
if (beanScope == null ||
beanScope.equals("singleton"))
{
//取出objPool的指定的Bean实例
Object bean = objPool.get(beanId);
//遍历<bean.../>元素的每个<property.../>子元素
for (Object prop : beanEle.elements())
{
Element propEle = (Element)prop;
//取得<property.../>元素的name属性
String propName = propEle.attributeValue("name");
//取得<property.../>元素的value属性
String propValue = propEle.attributeValue("value");
//取得<property.../>元素的ref属性
String propRef = propEle.attributeValue("ref");
//将属性名的首字母大写
String propNameCamelize = propName.substring(0 , 1).toUpperCase()
+ propName.substring(1 , propName.length());
//如果<property.../>元素的value属性值存在
if (propValue != null && propValue.length() > 0)
{
//获取设值注入所需的setter方法
Method setter = bean.getClass().getMethod(
"set" + propNameCamelize , String.class);
//执行setter注入
setter.invoke(bean , propValue);
}
if (propRef != null && propRef.length() > 0)
{
//取得需要被依赖注入的Bean实例
Object target = objPool.get(propRef);
//objPool池中不存在指定Bean实例
if (target == null)
{
//此处还应处理Singleton Bean依赖prototype Bean的情形
}
//定义设值注入所需的setter方法
Method setter = null;
//遍历target对象所所实现的所有接口
for (Class superInterface : target.getClass().getInterfaces())
{
try
{
//获取设值注入所需的setter方法
setter = bean.getClass().getMethod(
"set" + propNameCamelize , superInterface);
//如果成功取得该接口对应的方法,直接跳出循环
break;
}
catch (NoSuchMethodException ex)
{
//如果没有找到对应的setter方法,继续下次循环
continue;
}
}
//如果setter方法依然为null,
//则直接取得target实现类对应的setter方法
if (setter == null)
{
setter = bean.getClass().getMethod(
"set" + propNameCamelize , target.getClass());
}
//执行setter注入
setter.invoke(bean , target);
}
}
}
}
}
}