学习笔记-轻量级Java EE:模式--简单工厂

8 篇文章 0 订阅

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);
					}
				}
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值