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

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

几个疑问点:

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

}

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

时间: 2024-10-12 16:52:22

设计模式之abstract factory工厂模式的理解的相关文章

抽象工厂(Abstract Factory)模式

一.抽象工厂(Abstract Factory)模式 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态. 为了方便引进抽象工厂模式,引进一个新概念:产品族(Product Family).所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族.如图: 图中一共有四个产品族,分布于三个不同的产品等级结构中.只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品. 引进抽象工厂模式 所谓抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产

C#设计模式系列:简单工厂模式(Simple Factory)

1.简单工厂模式简介 1.1>.定义 简单工厂模式定义一个Factory类,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类. 简单工厂模式只需要一个Factory类. 简单工厂模式又称为静态工厂模式,Factory类为静态类或包含静态方法. 1.2>.使用频率  中 2.简单工厂模式结构 2.1>.结构图 2.2>.参与者 简单工厂模式参与者: ◊ Product:抽象产品类,将具体产品类公共的代码进行抽象和提取后封装在一个抽象产品类中. ◊ ConcretePr

设计模式(三): FACTORY工厂模式 -- 创建型模式

1.定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类. 2.适用场景 1.第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来.Java Collection中的iterator() 方法即属于这种情况. 2.第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给

常见的设计模式:单例模式、工厂模式、观察者模式、装饰模式与适配器模式

常见的设计模式:单例模式.工厂模式.观察者模式.装饰模式与适配器模式 这里可以阅读Terry Lee的设计模式系列来理解学习一下 1.4.1 单例模式 .NET设计模式(2):单件模式(Singleton Pattern)  http://terrylee.cnblogs.com/archive/2005/12/09/293509.html 1.4.2 抽象工厂模式 .NET设计模式(3):抽象工厂模式(Abstract Factory) http://terrylee.cnblogs.com/

设计模式学习(二)-简单工厂模式

---恢复内容开始--- 简单工厂设计模式 简单工厂模式定义: 简单工厂设计模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式.在简单工厂模式中,可以根据参数的不同返回不同类的实例.简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 简单工厂主要分为如下几个角色 抽象产品(abstract product):为所有具体产品的抽象表现,一般为抽象类 具体产品(product):为抽象产品的具体实现 生成产品工厂(facto

设计模式学习03—抽象工厂模式

1.动机与定义 工厂模式中,一个工厂仅仅能提供一个或一类产品,当产品种类较多,形成产品系列(比方我们要创建跨平台的button,菜单,文本框等等一系列GUI控件: 单纯使用工厂模式会产生大量工厂,并且后期维护也不方便,我们能够从产品中找到规律,假设产品等级相对固定,以后仅仅会新增产品族,那么我们就能够把整个产品族放到一个工厂创建,以后新增其它系统产品族也很方便,例如以下图: 这样的模式就是抽象工厂,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则须要面对多个产品等级结构,一个工厂等级结构能

初探设计模式(1)——工厂模式

从今天起,打算系统学习一下设计模式,先从工厂模式开始,本系列的文章只是对设计模式初步学习的总结,如有写的不对的地方欢迎指正. 什么是工厂模式呢?所谓工厂在我们的日常生活中就是生产产品的地方,如汽车工厂,玩具工厂等,在程序的世界中,设计到"生产产品"字眼的是什么?没错,就是创建对象! "工厂"通俗来说就是一个创建对象(产品)的地方.工厂模式(Factory Pattern)是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式,是 Java 中最常用的设

(设计模式之一)浅析简单工厂模式

简单工厂模式 举个两个例子: 我输入两个数字和(+ - * /)其中一个符号,计算出两个数的结果. 饲养员让(狗 猫 鸟 猪)其中一个动物 叫 这里就是一个简单的工厂模式, 用户只需要提供他需要的接口,而不需要知道具体的实现 工厂判断用户提供的接口,创建对应的子类对象, 返回父类变量给用户(这里涉及里氏替换原则:声明父类变量替换子类对象) 当后面追加新的操作类例如:求根类  求平方类 , 从数据安全角度: 只需要创建新的类继承于Operation抽象类 ,从而不影响其他操作类(+ - * /),

设计模式C++实现——抽象工厂模式

模式定义: 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类. 抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道实际产出的具体产品时什么.这样一来,客户就从具体的产品中被解耦了. 模式结构: 举例: 数据库访问程序设计,不同的数据库访问方式可能不一样,为了抽象对对不同数据库的访问,可以将数据库隐藏起来,提供统一的访问方式,用多态进行实现. UML设计: 编程实现及执行结果: #include <iostream> using namespace st