`
ku_sunny
  • 浏览: 37389 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
阅读更多
[img][/img]说工厂方法模式前先说下简单工厂模式吧!

按照设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,学习了此模式可以为后面的很多中模式打下基础。那好,我们就来了解下什么是简单工厂模式?

意图:根据提供给他的数据,返回几个可能类中的一个类的实例。

例如:我再一次带MM光临了麦当劳时,这次MM不想吃鸡翅了,而是选择了吃汉堡,可见这个时候ChickenFactory无法满足客户需要了,需要做出更改,方法就是再加一个工厂类:HamburgerFactory该类负责创建汉堡系列产品,这种方法造成的直接结果就是每一种产品都需要一个具体的工厂类,造成工厂过多,客户端使用不方便,因为我带MM去麦当劳不能由MM或者我决定鸡翅和汉堡是怎么生产出来的,我们只需要跟服务员说一声吃什么就可以了。 而工厂方法模式正是解决这种弊端而出现的,在工厂方法模式里,由一个抽象工厂类负责所有产品的创建,工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。

不多废话了,我还是喜欢从代码入手。
首先让大家看一个比较经典的简单工厂例子

package garden;

/**
 * 苹果
 * 
 * 由于苹果是多年生植物,因此多出一个treeAge 性质,
 * 描述苹果树的树龄
 *
 */
public class Apple implements Fruit {

	private int treeAge;

	// 生长
	public void grow() {
		log("Apple is growing...");
	}

	// 收获
	public void harvest() {

		log("Apple has been harvested.");
	}

	// 种植
	public void plant() {
		log("Apple has been planted.");
	}

	// 辅助方法
	public static void log(String msg) {
		System.out.println(msg);
	}

	// 树龄的取值方法
	public int getTreeAge() {
		return treeAge;
	}

	// 树龄的赋值方法
	public void setTreeAge(int treeAge) {
		this.treeAge = treeAge;
	}

}

package garden;

/**
 * 苹果
 * 
 * 由于苹果是多年生植物,因此多出一个treeAge 性质,
 * 描述苹果树的树龄
 *
 */
public class Apple implements Fruit {

	private int treeAge;

	// 生长
	public void grow() {
		log("Apple is growing...");
	}

	// 收获
	public void harvest() {

		log("Apple has been harvested.");
	}

	// 种植
	public void plant() {
		log("Apple has been planted.");
	}

	// 辅助方法
	public static void log(String msg) {
		System.out.println(msg);
	}

	// 树龄的取值方法
	public int getTreeAge() {
		return treeAge;
	}

	// 树龄的赋值方法
	public void setTreeAge(int treeAge) {
		this.treeAge = treeAge;
	}

}


package garden;

/**
 * 葡萄
 * 
 * 但由于葡萄分有籽和无籽两种,因此,比通常的水果多出一个seedless 性质
 * 
 */
public class Grape implements Fruit {

	private boolean seedless;

	// 生长
	public void grow() {
		log("Grape is growing...");
	}

	// 收获
	public void harvest() {
		log("Grape has been harvested.");
	}

	// 种植
	public void plant() {
		log("Grape has been planted.");
	}

	// 辅助方法
	public static void log(String msg) {
		System.out.println(msg);
	}

	// 有无籽的取值方法
	public boolean getSeedless() {
		return seedless;
	}

	// 有无籽的赋值方法
	public void setSeedless(boolean seedless) {
		this.seedless = seedless;
	}

}


package garden;

/**
 * 草莓
 * 
 * Strawberry 类实现了Fruit 接口,因此,也是水果类型的子类型
 */
public class Strawberry implements Fruit {

	// 生长
	public void grow() {
		log("Strawberry is growing...");

	}

	// 收获
	public void harvest() {

		log("Strawberry has been harvested.");
	}

	// 种植
	public void plant() {
		log("Strawberry has been planted.");
	}

	// 辅助方法
	public static void log(String msg) {
		System.out.println(msg);
	}

}

package garden;

/**
 * 当没有此类水果所抛出的一次
 *
 */
public class BadFruitException extends Exception {
	
	private static final long serialVersionUID = 3677167960651698463L;

	public BadFruitException(String msg) {
		super(msg);
	}

}


package garden;

/**
 * 农场的园丁
 * 
 * FruitGardener 类会根据客户端的要求,创建出不同的水果对象,比如苹果(Apple),
 * 葡萄(Grape)或草莓(Strawberry)的实例。而如果接到不合法的要求, FruitGardener 类会抛出BadFruitException
 * 异常
 * 
 */
public class FruitGardener {
	// 静态工厂方法
	public static Fruit factory(String which) throws BadFruitException {

		if (which.equalsIgnoreCase("apple")) {

			return new Apple();
		} else if (which.equalsIgnoreCase("strawberry")) {

			return new Strawberry();
			
		} else if (which.equalsIgnoreCase("grape")) {
			return new Grape();
			
		}else {
			throw new BadFruitException("Bad fruit request");

		}

	}

}


package garden;

/**
 * 这样就可以种各种水果了
 * 
 */
public class Run {

	public static void main(String[] args) {

		try {

			// 种植葡萄
			FruitGardener.factory("grape").plant();
			FruitGardener.factory("grape").grow();
			FruitGardener.factory("grape").harvest();
			System.out.println("==================================");

			// 种植苹果
			FruitGardener.factory("apple").plant();
			FruitGardener.factory("apple").grow();
			FruitGardener.factory("apple").harvest();
			System.out.println("==================================");

			// 种植草莓
			FruitGardener.factory("strawberry").plant();
			FruitGardener.factory("strawberry").grow();
			FruitGardener.factory("strawberry").harvest();
			System.out.println("==================================");

		}

		catch (BadFruitException e) {

		}

	}

}

具体实现可看garden包,在factory-pattern 文件中


由于接下来代码过多我就不一一贴出来,全部已经打包放在factory2-pattern文件中了
敬请谅解。

下面通过一个例子说说简单工厂模式和工厂方法模式。
    这些例子的都是来自现实的一个比萨店,由于比萨店每天需要为客户提供不同种比萨原型
然而现在该点已经在负责切、烤、烘等操作了,现在如果有人需要一种CheesePizza,如果该点还要从原材料开始先磨出比萨原型,再通过各种加工未免会出现过程太久让顾客等的不耐烦,而且该店如果负责的 工序太多,也容易出现差错。于是乎,该店决定让比萨工厂专门负责提供比萨原型的饼,然后在通过自己加工就可以个顾客了

/**
 * 披萨店
 * 用简单工厂模式
 * 
 * 特点:主要让工厂负责生产所有类型的披萨,针对接口编程
 * 
 * 优点:针对接口编程可以隔离掉以后系统可能发生的一大堆改变
 *       方法简单易理解,思路清晰
 * 缺点:不易管理,当子类增删改后得同时维护工厂类导致耦合性太强
 *       违背开闭原则即扩展开发修改关闭
 * 
 * 说明:简单的工厂其实不只是一个设计模式,反而比较像一种编程习惯。
 * 但不要因为他不是一个模式就忽略的他的用途 
 */

 具体代码看附件 simple_factory包


    接下来由于这个点开大了,他们现在不同的地区开加盟店了,而且不同地方的加盟店在原店味道大体不变的情况下他们还有一些自己地方的特色或者说加入一些改良,如果还是按照简单工厂方法来设计的话,或许你会觉得每次我有新品种的比萨产生或者销量不好的比萨给淘汰了,都需要修改原工厂类,这样大家会感觉等到比萨品种一变多就很难维护。所以在此作者就推荐了一种工厂方法的模式设计,让自己地方的比萨自己维护字的的,这样具体的类型就有分店决定,就不至于耦合性太强了,也不用让总部关系具体的类型,减少错误,这样也符合倒置依赖原则。 
    其实这也符合做人的道理,大家玩玩会看到做官或做领导的说话都是很笼统很抽象的,如果太具体了难免会出差错。
    接下去还是看具体代码吧!
/**
 * 披萨店
 * 用工厂方法模式
 * 
 * 定义:定义了一个创建对象接口,单由子类决定要实例化的类时哪一个。
 *       让类把实例化推迟到子类
 * 
 * 特点:让已有一个PizzaStore做为超类
 *       让每域类型都继承这个类,这样每个子类各种决定如何做比萨
 * 
 * 优点:降低代码耦合性,符合倒置依赖原则。
 *       简单工厂把全部事情在一个地方处理完,然而工厂方法却是创建一个框架,
 *       让子类如何实现
 *       
 * 适用场合:
 * 	 需要客户代码从需要实例化的具体类中解耦。或者如果你目前还不知道将来需要实例化那些具体类时。
 *      
 *       
 */

具体例子实现看附件factory_method包

    在实际生活中,如果你让一个工厂通过原始材料如果做个原型的饼可能需要的原材料是大米、小麦、猪肉、牛肉……一些产品。然而在实际生活中,许多工厂喜欢偷工减料,所以为了杜绝这种现象的发生往往需要按照总部要求制作的原料工厂开在地方,这些原料工厂专门把如做好的火腿肠给他们,而不是仅仅提供肉和面粉本身。在实现这些原料工厂时他们一定要严格符合总部指定的要求制作,且总部已经为各种这些原料的实现提供模版了。

/**
 * 披萨店 -- 抽象工厂模式
 * 用工厂方法模式--没看错抽象工厂模式中确实用到了工厂方法模式
 * 
 * 定义:提供一个接口,用于创建相关或依赖对象家族
 *       而不需要确定具体类
 * 
 * 特点:抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道
 *       或关心实际产出的具体产品是什么也即由子类定义了产品被产生的方法。
 *       这样依赖,客户就从具体的产品中被解耦。 
 *       本例子中就是大家只需要关心所提供的材料,而不需要知道此材料的原材料
 *       如提供香肠而不用关心香肠是用什么做成的
 * 
 * 缺点:如果加入新产品就必须改变接口(这点工厂方法做的比较好),因为它是创建一个
 *       家族的产品所有需要一个大接口
 * 
 * 与工厂方法的不同点:
 *    1.抽:对象。工厂:类
 *    2.抽:通过组合创建对象。工厂:通过继承并覆盖他的方法,而是让子类创建对象(这样子类决定类型)
 *    3.抽: 加入新产品必须改变接口. 工厂:只需要改变子类的实现即可
 *    4.抽: 用来创建一个家族。工厂:创建一个产品
 *    
 * 与工厂方法相同点:
 *    1.都可以从具体产品中解耦,可以把一群相关的产品集合起来
 *       
 *  适用场合:
 * 	当你需要创建产品家族和想让制造的相关产品集合起来时
 */

具体代码实现看附件abstract_factory包

分享到:
评论

相关推荐

    Java设计模式-工厂方法

    Java设计模式,工厂方法的Demo,具体的思想有很多讲得很好的老师,我是看厉风行老师的视频学的,讲得不错,简单易懂

    Java设计模式-简单工厂

    Java设计模式,简单工厂的Demo,具体的思想与实现有很多讲得很好的老师,我是看厉风行老师的视频学的,讲得不错,简单易懂

    Java设计模式-抽象工厂

    Java设计模式,抽象工厂的Demo,具体的思想与实现有很多讲得很好的老师,我是看厉风行老师的视频学的,讲得不错,简单易懂

    JAVA设计模式-day2.pdf

    JAVA设计模式-day2,请的行业大能讲得课程,涉及:创建模式(5种: 1、 工厂方法模式(Factory Method); 2、 抽象工厂模式; 3、 单例模式(Singleton) • 4、 建造者模式(Builder); 5、 原型模式(Prototype...

    研磨设计模式-part2

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式-part4

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式-part3

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    Head First 设计模式 JAVA源码

    所有的设计模式Java实现。 第一讲:简单工厂模式 第二讲:工厂方法模式 第三讲:抽象工厂模式 第四讲:工厂模式在开发中的运用 第五讲:单例模式 第六讲:原型模式 ...第三十讲:设计模式总结

    设计模式PPT.rar

    01第一讲简单工厂模式 02第二讲工厂方法模式 03第三讲抽象工厂模式 04第四讲工厂模式在开发中的运用 05第五讲单例模式 06第六讲原型模式 07第七讲建造者模式 08第八讲装饰模式 09第九讲策略模式 10第十讲观察者模式 ...

    设计模式:可复用面向对象软件的基础--详细书签版

    设计模式捕获了随时间进化与发展的问题的求解方法,因此它们并不是人们从一开始就采用的设计方案。它们反映了不为人知的重新设计和重新编码的成果,而这些都来自软件开发者为了设计出灵活可复用的软件而长时间进行的...

    从模式讲到设计模式再到面向对象设计模式

    目前最有影响力的书籍是:《设计模式:可复用面向对象软件的基础》,它共编录了23种设计模式,分三大类别:创建型模式、结构型模式、行为模式,其中有一种创建型模式是抽象工厂设计模式。 在学习抽象工厂设计模式...

    尚硅谷设计模式源码笔记课件.zip

    共150讲,时长共 33...1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括...

    PHP高级程序设计-模式-框架-测试

    书中首先从OOP 采用的机制—— 抽象类、接口、契约式编程开始讲起,然后介绍了静态方法、单例模式、工厂模式和PHP 6 的新特性等内容,接着介绍了测试和文档方面的内容,还介绍了标准PHP 库SPL 方面的知识以及PHP ...

    .net设计模式(上海科技李建忠老师讲)视频(25-3、抽象工厂)

    我想不会涉及版权问题吧,因为视频没有密码什么的,所以大家共享一下(若涉及版权请给以警告,本人自会撤出),相当经典的设计讲座视频教程,上海科技李建忠老师讲,共25集,我会逐步上传,值得中高级程序员予以关注...

    研磨设计模式(完整带书签).part2.pdf

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    [浪曦原创]JAVA设计模式 第2讲 单态模式和简单工厂模式(jzkangta).rar

    [浪曦原创]JAVA设计模式 第2讲 单态模式和简单工厂模式(jzkangta).rar

    C#面向对象设计模式纵横谈(视频与源码)

    C#面向对象设计模式纵横谈(5):Factory Method 工厂方法模式(创建型模式) C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式) C#面向对象设计模式纵横谈(7):Adapter 适配器模式(结构型模式) C#面向...

    java设计模式

    目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式

Global site tag (gtag.js) - Google Analytics