设计模式之工厂模式(Factory Pattern)

一.什么是工厂模式?

1.“简单工厂模式”,Simple Factory Pattern

也就是常用的在Factory类中定义静态方法负责new对象的方式。

摘要中提到过“严格地说,这种被称为“简单工厂模式”的方式根本不能称之为“模式””,虽然静态工厂方法并不是真正的“设计模式”,但这种方式的应用也很广泛,也能带来一些好处,所以我们不能因为它不是“设计模式”就抛弃它。

2.工厂方法模式,Factory Method Pattern

是工厂模式的核心

定义一个抽象的“工厂方法”来负责new对象,由该类的扩展类来实现如何new的过程

这种方式成功分离了对象创建过程与对象行为(暂不做解释),确切地说是把对象创建“下放”到了子类。(注意这里的动词——“下放”)

3.抽象工厂模式,Abstract Factory Pattern

是对工厂方法模式的一种应用与扩展

把多个“工厂方法”封装在一个抽象工厂类中,以实现“new一组对象”的目的

二.一般方式(不用工厂模式)

我们来开一个小店卖衣服,首先需要ColthesStore类负责接收订单返回做好的衣服,ClothesStore类需要依赖Clothes类,毕竟要操作的具体对象是Clothes,ClothesStore中还要有做衣服的工序(制作、加工装饰。。)

那么我们的ClothesStore将是这样的:

package FactoryPattern;

/**
 * @author ayqy
 * 不使用工厂模式,直接创建具体对象
 *
 */
public class ClothesStore {

	String type;//定义衣服类型
	Clothes clothes;//衣服对象

	/**
	 * @author ayqy
	 * 定义内部类Clothes
	 *
	 */
	class Clothes{
		String type;//类型
		String desc;//描述
		String cloth;//布料

		public Clothes(String type, String desc, String cloth){
			this.type = type;
			this.desc = desc;
			this.cloth = cloth;
		}

		public String toString(){
			return type+ "," + desc + "," + cloth;
		}
	}

	public ClothesStore(String type){
		this.type = type;
	}

	/**
	 * @return 返回未经装饰加工的衣服
	 */
	private Clothes createClothes(String type){
		if(type.equals("外套")){
			return new Clothes("外套", "一件好看的外套", "麻布");
		}else if(type.equals("内衣")){
			return new Clothes("内衣", "一件舒适的内衣", "棉布");
		}else
			return null;
	}

	/**
	 * @return 返回做好的衣服
	 */
	public Clothes getClothes(){
		clothes = createClothes(type);
		decorate(clothes);//对衣服进行装饰

		return clothes;
	}

	private void decorate(Clothes clothes){
		//给衣服添加装饰(图案、纹样等等)
		System.out.println("精心装饰完毕,衣服变得更漂亮了");
	}
}

P.S.代码中把Clothes定义为内部类,只是为了节省篇幅简化结构,效果一样

我们发现ClothesStore对Clothes有着很强的依赖(过分依赖“具体”可不是一件好事儿。。),一旦Clothes发生变化(如有了新的成员变量与成员函数),我们的ClothesStore可能就不得不跟着修改了,尤其是负责new衣服对象的部分:

/**
* @return 返回未经装饰加工的衣服
*/
private Clothes createClothes(String type){
if(type.equals("外套")){
		return new Clothes("外套", "一件好看的外套", "麻布");
	}else if(type.equals("内衣")){
		return new Clothes("内衣", "一件舒适的内衣", "棉布");
	}else
		return null;
}

一旦有了新的type我们就要添加一个else if来应对变化

而且由于ClothesStore与具体的Clothes类绑定在一起,导致ClothesStore不易于扩展,很难复用

三.“简单工厂模式”

把createClothes方法移动到ClothesFactory中作为一个静态工厂方法,就像这样:

package FactoryPattern.SimpleFactoryPattern;

/**
 * @author ayqy
 * 定义静态工厂方法
 *
 */
public class ClothesFactory {
	/**
	 * @return 返回未经装饰加工的衣服
	 */
	public static Clothes createClothes(String type){
		if(type.equals("外套")){
			return new Clothes("外套", "一件好看的外套", "麻布");
		}else if(type.equals("内衣")){
			return new Clothes("内衣", "一件舒适的内衣", "棉布");
		}else
			return null;
	}
}

P.S.这次必须把Clothes拿出来作为一个独立的类了(内部类无法访问),除此之外,ClothesStore中的getClothes方法也要做相应改变。。不要在意这些细节

应用简单工厂模式之后,我们确实把new对象的部分独立出来了,这样做的好处是:

当Clothes发生变化时,我们可以在ClothesFactory中直接修改create方法,而不是在ClothesStore的长篇代码中寻找Create部分

而且与之前的“一般方式”对比,代码几乎没有发生什么变化,很容易把之前的代码改成应用简单工厂模式之后的代码,所以很多开发人员喜欢这种方式

-------

“简单工厂模式”并不是真正的工厂模式,它的优势也是极其有限的,不过没关系,我们还有工厂方法模式,这次是货真价实的工厂模式

四.工厂方法模式

定义抽象的“工厂方法”,负责具体实现,全新的ClothesStore将是这样的:

package FactoryPattern.FactoryMethodPattern;

/**
 * @author ayqy
 * 使用工厂方法模式,定义抽象的工厂方法来new产品
 *
 */
public abstract class ClothesStore {

	String type;//定义衣服类型
	Clothes clothes;//衣服对象

	public ClothesStore(String type){
		this.type = type;
	}

	//定义工厂方法,由扩展类来实现具体制作细节
	public abstract Clothes createClothes(String type);

	/**
	 * @return 返回做好的衣服
	 */
	public Clothes getClothes(){
		clothes = createClothes(type);
		decorate(clothes);//对衣服进行装饰

		return clothes;
	}

	private void decorate(Clothes clothes){
		//给衣服添加装饰(图案、纹样等等)
		System.out.println("精心装饰完毕,衣服变得更漂亮了");
	}
}

我们发现ClothesStore变成Abstract的了,里面封装了衣服的制作工序以及实现细节,但并没有实现Create过程

下一步是要扩展ClothesStore类,实现具体Create细节,就像这样:

package FactoryPattern.FactoryMethodPattern;

/**
 * @author ayqy
 * 扩展ClothesStore,实现具体制作细节
 *
 */
public class DefaultClothesStore extends ClothesStore{

	public DefaultClothesStore(String type) {
		super(type);
	}

	/*
	 * 实现具体制作细节
	 */
	@Override
	public Clothes createClothes(String type) {
		if(type.equals("外套")){
			return new Clothes("外套", "一件好看的外套", "麻布");
		}else if(type.equals("内衣")){
			return new Clothes("内衣", "一件舒适的内衣", "棉布");
		}else
			return null;
	}
}

嗯,现在我们已经成功应用工厂方法模式了,让我们来看看相比之前的简单工厂模式,这个货真价实的工厂模式有哪些特点

1.同样实现了new对象的具体过程与对象行为的分离,但不同的是我们是利用继承(扩展)来实现的,也就是开篇提到的“下放”(把具体实现放到更低的类层次上)

2.每一个具体Store都必须实现自己的Create细节,但同时又可以利用基类Store的制作工艺(decorate方法等等)

3.一个抽象的工厂方法轻松实现了工厂模式(甚至Factory自始至终根本没有出现,但我们确实已经实现了“工厂”,不是吗?)

五.抽象工厂模式

抽象工厂模式是对上一种方式的扩展,在上面我们只能Create一个产品,但很多时候我们需要Create一组产品,比如衣服的原料,包括布料、染料、线、纽扣等等,这时候就需要应用抽象工厂模式来实现:

package FactoryPattern.AbstractFactoryPattern;

/**
 * @author ayqy
 * 定义原料工厂
 *
 */
public abstract class ResourcesFactory {
	public abstract Cloth getCloth();//获取布料
	public abstract Color getColor();//获取染料
	public abstract Button getButton();//获取纽扣
	//需要的其它工厂方法
}

抽象工厂中的类型都是自定义接口,例如:

package FactoryPattern.AbstractFactoryPattern;

/**
 * @author ayqy
 * 定义Cloth接口
 */
public interface Cloth {
	//属性
	//行为
}

有了原料工厂,那么ClothesStore也要做相应的改变来适应这种新的结构:

package FactoryPattern.AbstractFactoryPattern;

/**
 * @author ayqy
 * 扩展ClothesStore,实现具体制作细节
 *
 */
public class DefaultClothesStore extends ClothesStore{

	public DefaultClothesStore(String type, ResourcesFactory res) {
		super(type, res);
	}

	/*
	 * 实现具体制作细节
	 */
	@Override
	public Clothes createClothes(String type) {
		if(type.equals("外套")){
			//获取所需原料
			Cloth cloth = res.getCloth();
			Color color = res.getColor();
			Button button = res.getButton();
			//制作衣服
			return new Clothes("外套", color.toString() + button.toString(), cloth.toString());
		}else if(type.equals("内衣")){
			//获取所需原料
			Cloth cloth = res.getCloth();
			Color color = res.getColor();
			Button button = res.getButton();
			//制作衣服
			return new Clothes("内衣", color.toString() + button.toString(), cloth.toString());
		}else
			return null;
	}
}

现在创建Store对象时需要一个具体ResourcesFactory参数(具体的原料工厂实现了所有的getXXX工厂方法),具体的Store只负责具体制作过程,需要什么原料都可以从ResourceFactory中取得,具体Store做衣服后,由Store基类负责工艺加工(decorate方法等等),最后由具体的Store返回精加工完毕的衣服

整个结构很疏松,低耦合,易扩展

-------

除此之外,还有必要提及一个OO设计原则——“依赖倒置原则”

通过观察类结构我们可以发现:

高层组件Store依赖Clothes,同时低层组件ResourcesFactory也依赖Clothes(这就是“依赖倒置”,即低层组件反过来依赖高层组件,同时高低层组件都依赖抽象)

这样的设计有着极易扩展的优势(抽象意味着可扩展。。)

五.总结

其实开篇第一部分就是总结,这里要强调的是:事物都有两面性,一个好的东西必然存在缺点,设计模式也不例外。

抽象工厂模式看起来真的不错,但是也存在致命的缺点:多级抽象引起的结构复杂化问题

时间: 2024-11-10 01:04:35

设计模式之工厂模式(Factory Pattern)的相关文章

【设计模式】工厂模式 Factory Pattern

1)简单工厂(不是模式) 简单工厂只是一种变成习惯,并非23种设计模式之一. 简单工厂提供将实例话那种类型留给运行时判断,而非编译时指定.简单工厂模式就是由一个工厂类根据传入的参数决定创建出哪一个类的实例. 角色: 工厂类:接收参数,返回参数指定的类的实例. 抽象产品:返回实例的类型,具体产品的基类. 具体产品:继承自抽象产品的类. 2)工厂方法模式 沿着上面的思路,创建的接口是稳定的,但是创建对象剧烈变化.将稳定的接口抽象成基类,让子类确定实例哪个产品,将实际创建工作推迟到子类中. 工厂方法用

设计模式一 工厂模式Factory

设计模式一 工厂模式Factory 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象. 在这些情况,新对象的建立就是一个 "过程",不仅是一个操作,像一部大机器中的一个齿轮传动. 模式的问题:你如何能轻松方便

Android设计模式之一个例子让你彻底明白工厂模式(Factory Pattern)

提出疑问 这几天研究工厂模式的时候,看到网上的一些文章中举的例子我就很疑惑,我相信这也是许多人的疑惑:工厂模式的功能就是创建实例,我们创建实例直接new不就完了吗,干嘛还得再封装一层工厂类,然后用工厂类再去new出这个实例?这不多此一举吗? 比如我看到这样的例子,我们的用户分为金牌用户和银牌用户,我们要创建一个金牌用户或者银牌用户. 定义一个用户接口 public interface ICustomer { String describe(); } 金牌用户实现类 public class Go

23种设计模式--工厂模式-Factory Pattern

一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例就就依赖与这个类,2者之间的耦合度就高,此时我们就可以使用面向对象的去解决这个问题,将变化点封装起来,这就是我们将要首先引入的简单工厂模式:先来说一个场景,比如我们吃水果这个例子吧,我们有时候想吃苹果,有时候想吃橘子,但是每次都需要去买这些水果,后来有个水果店,又卖橘子,又卖苹果,这个水果店就当于简

创建型模式篇(工厂模式Factory Pattern)

一.工厂模式(Factory Pattern) 1.定义: 在软件系统,经常面临着"某个对象"的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口.提供一种封装机制来隔离这个对象的变化,从而保持系统中其他依赖这个变化对象的对象,就要用到工厂模式. 2.目的:定义一个用户创建对象的接口,让子类决定实例化哪一个类,FactoryMethod使一个类的实例化延迟到它的子类. 3.结构图: 工厂模式:定义一个用于创建对象的接口,但是让子类决定实例化哪个

抽象工厂模式(abstarct factory pattern)和工厂模式(factory pattern)的比较

抽象工厂模式和工厂模式从字面上来看就有必然的联系,他们都是创建型模式.总结来说,工厂模式(factory pattern)只是个小工厂,只提供一层接口的实现类的输出,而抽象工厂模式(abstract factory pattern)是工厂模式的进一步升级,可以上升到两层以上的工厂模式继承,是工厂的工厂.一计算机来说,工厂模式可以是不同型号显示器,CPU或者网卡的提供者,而抽象工厂模式是显示器工厂.CPU工厂和网卡工厂的工厂.可以通过抽象工厂来获得CPU工厂,进而获得某个型号的CPU.整个依赖关系

工厂模式(factory pattern)

工厂模式主要用来封装对象的创建,有3种分类:简单工厂(simple factory).工厂方法(factory method).抽象工厂(abstract factory). 简单工厂包括3种组成元素:抽象产品.具体产品.具体工厂(简单工厂),结构图如下: C++实现: //抽象产品 class Car { public: virtual string getDescription() = 0; }; //具体产品 class Audi : public Car { string getDesc

设计模式~简单工厂模式(Factory)

简单工厂模式Simple Factory根据提供给它的数据,返回一个类的实例.通常它返回的类都有一个公共的父类(或者接口对象). 简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类.简单工厂实例化的类具有相同的接口或者基类,在子类比较固定并不需要扩展时,可以使用简单工厂.如数据库生产工厂就是简单工厂的一个应用.         采用简单工厂的优点是可以使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性:缺点是可实例化的类型在编译期间已经被确定,如果增加新类 型,

设计模式之工厂模式 Factory实现

simpleFactory //car接口 public interface Car { void run(); } //两个实现类 public class Audi implements Car{ public void run() { System.out.println("奥迪在跑"); } } public class Byd implements Car{ public void run() { System.out.println("Byd在跑");

设计模式之--工厂模式(Factory)

定义:Defined an interface for creating an object,but let subclasses decide which class  to instantiate.Factory Method let a class defer instantiation to subclass(定义一个创建对象的接口,让子类类型来决定实例化对象.工厂方法能够使类的实例化延迟到具体的子类)工厂方法的泛型应用是关键 类图: 一 定义产品 1 定义产品接口 package dm