码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式之abstract factory工厂模式的理解

时间:2014-08-30 23:09:22      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:设计模式   工厂模式   spring   java   

研究了一下工厂模式,对它的应用场景和网上的众多说法进行了思考,总结如下。


几个疑问点:

1、网上说用factory,就可以不用自己new了,但是疑问在于,不直接依赖,转而间接依赖,作用是什么?节省了代码量?易于扩展?

2、书上说,一个系统要独立于它的产品的创建、组合和表示时。一个系统要由多个产品系列中的一个来配置时。当你要强调一系列相关的产品对象的设计以便进行联合使用时。当你提供一个产品类库,而只想显示它们的接口而不是实现时,就应该使用工厂模式。但是疑问在于,这他妈说的都是啥?


于是开始了我的思考过程,思路如下:

1、书上说的,等我领悟了,我就成仙了,作者这么写书,或者翻译的人这么写,就是没道德,根本不考虑看书的人的感受,这里不多吐槽了,免得跑题

2、开始思考网上的众多说法,试图发现他们背后的出发点。

-如果说代码量节省,其实照着网上的demo来看,表面上想一下,并没有节省多少代码,反而多了很多接口,但是如果在大工程里,类很多又会怎么样呢?如果仅仅是简单的把new改成getFromFactory,显然是没有发挥出factory的优势。

-如果说解耦,确实是,不过原来的直接依赖,改成间接依赖,有什么作用呢?好像没什么作用,因为消费者依然要向工厂索要自己想要的类型


以上思考没有答案后,开始试图找到现实中的例子,然后考虑其实际意义,然后就想到了spring的beanFactory,这是个典型的工厂模式,那么它的意义在于什么呢?我决定顺着spring往里找答案。

n年前面试的时候,被问到过,“用了ioc有什么好处”?我答到,“不用new了”,问,“那我不用spring,全都自己new又怎么样呢?”,我无语。不过如果现在让我再次回答这个问题,我会说:“解耦、对bean的统一管理、实现了依赖关系的反转”

而“对bean的统一管理、实现依赖关系的反转”,正是靠factory模式实现的。

试想一下复杂的场景,我作为一个对外提供bean的管理员,想给所有从我这里出去的bean打个标签,怎么做?我想统一要求,我给出的bean,被调用的时候,都要发个消息给我,以统计调用次数,怎么做?前提是不能改变bean内部的逻辑?(实际上也不可能一个一个的去改),答案就是factory+proxy,这就是统一的管理

再考虑另一个问题——ioc,当使用了factory模式,factory即充当了一个bean依赖关系的维护者,即从原来的A必须依赖B实现一个功能,变成了,A实现功能不知道要依赖谁,factory告诉它,这里网上的demo就有一个容易让人误解的地方:从原来的new改成getFromFactory(“beanName”),我就是这里想不清楚——这依赖关系其实没变,只是多了一层而已。但是实际上不是,spring的bean管理,是通过从属于spring的配置文件来维护bean的依赖关系的,实际互相调用前,spring早就按照这份管理文件将各个bean装配好了,这就是所谓的控制反转了


这样bean的功能变得更单一,复杂的关系维护交给了工厂,到这里也就没什么疑惑的了,随即写了一段程序,模拟了spring的加载bean的过程:


工厂接口:

public interface AbstractFactory {
	
	Object getBean(String beanName);

}

工厂实现:

public class ApplicationContext implements AbstractFactory {
	
	private BeanDefinitionRegistry beanMapper = new BeanDefinitionRegistry();
	
	private Map<String,Object> beans = new HashMap<String,Object>();
	
	public Object getBean(String beanName) {
		return beans.get(beanName);
	}
	
	public ApplicationContext () {
		
		init();
		
	}
	
	private void init() {
		loadBean();
		wireBean();
	}
	
	private void wireBean() {
		
		for (Entry<String,Object> entry : beans.entrySet()) {
			Object bean = entry.getValue();
			Class c = bean.getClass();
			Field[] fields = c.getDeclaredFields();
			
			wireField(fields,bean);
		}
	}

	private void wireField(Field[] fields,Object bean) {
		
		for (Field field : fields) {
			try {
				field.setAccessible(true);
				Object value = field.get(bean);
				if (value == null) {
					field.set(bean, beans.get(field.getName()));
				}
			} catch (Exception e) {}
		}
		
	}

	private void loadBean() {
		for (Entry<String, Object> entry : beanMapper.getBeanDefinition().entrySet()) {
			doLoadBean(entry.getKey(),entry.getValue());
		}
	}

	private void doLoadBean(String key, Object value) {
		
		Class c = (Class)value;
		try {
			Object o = c.getConstructor().newInstance(null);
			beans.put(key, o);
		} catch (Exception e) {}
		
	}

}


bean的配置模拟:

public class BeanDefinitionRegistry {
	
	public Map<String,Object> beanDefinition = new HashMap<String,Object>();
	
	public BeanDefinitionRegistry() {
		
		beanDefinition.put("serviceA", ServiceA.class);
		beanDefinition.put("serviceB", ServiceB.class);
		
	}

	public Map<String, Object> getBeanDefinition() {
		return beanDefinition;
	}


}

两个有依赖关系的服务:

public class ServiceA {
	
	private ServiceB serviceB;

	public ServiceB getServiceB() {
		return serviceB;
	}

	public void setServiceB(ServiceB serviceB) {
		this.serviceB = serviceB;
	}
	
	public String getCurrentDate() {
		return serviceB.getCurrentDate();
	}
	
}
public class ServiceB {
	
	public String getCurrentDate() {
		return new Date().toString();
	}

}
最后的测试类:

public class Tester {
	
	public static void main(String[] args) {
		
		AbstractFactory beanFactory = new ApplicationContext();
		
		ServiceA serviceA = (ServiceA)beanFactory.getBean("serviceA");
		
		String currentDate = serviceA.getCurrentDate();
		
		System.out.println(currentDate);
	}

}


到这里,工厂模式算是有了自己的理解,欢迎交流,欢迎挑战









设计模式之abstract factory工厂模式的理解

标签:设计模式   工厂模式   spring   java   

原文地址:http://blog.csdn.net/fifa_016/article/details/38948281

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!