1. 工厂方法模式简介

1.1 定义

  工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式是以一个类的实例化延迟到其子类。

  Factory Method模式用于在不指定待创建对象的具体类的情况下创建对象。

  Factory Method模式的主要意图是隐藏对象创建的复杂性。Client通常不指定要创建的具体类,Client将面向接口或抽象类进行编码,让Factory类负责创建具体的类型。通常Factory类有一个返回抽象类或者接口的静态方法。Client通常提供某种信息让Factory类使用提供的信息来确定创建并返回哪个子类。

  将创建子类的责任抽象出来的好处是允许Client完全无需考虑依赖类是如何创建的,这遵守依赖倒置原则(Dependency Inversion Principle,DIP)。Factory Method模式另外一个好处是把负责对象创建的代码集中起来,如果需要修改对象生成方式,可以轻松定位并更新,而不会影响到依赖它的代码。

1.2 使用频率

  

2. 工厂方法模式结构

2.1 结构图

2.2 参与者

  工厂方法模式参与者:

  ◊ Product:Product角色,定义工厂方法所创建的对象的接口

  ◊ ConcreteProduct:具体Product角色,实现Product接口

  ◊ Factory

    ° 抽象的工厂角色,声明工厂方法,该方法返回一个Product类型的对象

    ° Factory可以定义一个工厂方法的默认实现,返回一个默认的ConcreteProduct对象。可以调用工厂方法以创建一个Product对象。

  ◊ ConcreteFactory:具体的工厂角色,创建具体Product的子工厂,重写工厂方法以返回一个ConcreteProduct实例

3. 工厂方法模式结构实现

  Product.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
/// <summary>
/// 定义Product抽象类,Client调用Product抽象类,并由Factory来创建具体类。
/// </summary>
public abstract class Product
{
}
}

  ConcreteProductA.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
public class ConcreteProductA : Product
{
}
}

  ConcreteProductB.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
public class ConcreteProductB : Product
{
}
}

  Factory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
public abstract class Factory
{
public abstract Product CreateProduct();
}
}

  ConcreteFactoryA.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
public class ConcreteFactoryA : Factory
{
public override Product CreateProduct()
{
return new ConcreteProductA();
}
}
}

  ConcreteFactoryB.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Structural
{
public class ConcreteFactoryB : Factory
{
public override Product CreateProduct()
{
return new ConcreteProductB();
}
}
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using DesignPatterns.FactoryMethodPattern.Structural; namespace DesignPatterns.FactoryMethodPattern
{
class Program
{
static void Main(string[] args)
{
Factory[] factories = new Factory[];
factories[] = new ConcreteFactoryA();
factories[] = new ConcreteFactoryB(); foreach (Factory factory in factories)
{
Product product = factory.CreateProduct();
Console.WriteLine("Created {0}", product.GetType().Name);
}
}
}
}

  运行输出:

Created ConcreteProductA
Created ConcreteProductB
请按任意键继续. . .

4. 工厂方法模式实践应用

  假设你现在是一家KFC的管理者,要给顾客提供一系列的食品,如鸡翅、鸡腿等,顾客没要求一种食品,KFC应当可以很快生产出来,采用工厂模式来实现这个过程。

  KFCFood.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
/// <summary>
/// 抽象的KFC食品,Product角色
/// </summary>
public abstract class KFCFood
{
public abstract void Display();
}
}

  Chicken.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
public class Chicken : KFCFood
{
public override void Display()
{
Console.WriteLine("鸡腿 + 1");
}
}
}

  Wings.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
public class Wings : KFCFood
{
public override void Display()
{
Console.WriteLine("鸡翅 + 1");
}
}
}

  IKFCFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
public interface IKFCFactory
{
KFCFood CreateFood();
}
}

  ChickenFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
public class ChickenFactory : IKFCFactory
{
public KFCFood CreateFood()
{
return new Chicken();
}
}
}

  WingsFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.FactoryMethodPattern.Practical
{
public class WingsFactory : IKFCFactory
{
public KFCFood CreateFood()
{
return new Wings();
}
}
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using DesignPatterns.FactoryMethodPattern.Practical; namespace DesignPatterns.FactoryMethodPattern
{
class Program
{
static void Main(string[] args)
{
// 定义一个鸡腿工厂
IKFCFactory factory = new ChickenFactory();
// 生产鸡腿
KFCFood food1 = factory.CreateFood();
food1.Display();
// 生产鸡腿
KFCFood food2 = factory.CreateFood();
food2.Display();
// 生产鸡腿
KFCFood food3 = factory.CreateFood();
food3.Display();
}
}
}

  运行输出:

鸡腿 +
鸡腿 +
鸡腿 +
请按任意键继续. . .

  在以上例子中,使用工厂模式的好处:

  1>. 客户端在创建产品的时候只需指定一个子工厂而无需了解该子工厂具体创建什么产品;

  2>. 当需求有变动,要不food1、food2、food3均改为“鸡翅”的时候,只需将

IKFCFactory factory = new ChickenFactory();

  改为

IKFCFactory factory = new WingsFactory();

  即可;

  3>. 在工厂方法模式中,核心的工厂类不是负责所有产品的创建,而是将具体的创建工作交给子类ConcreteFactory去做。工厂类仅仅负责给出具体工厂必须实现的接口,而不涉及哪一个产品类被实例化这种细节。工厂方法模式可以使得系统在不需要修改原有代码的情况下引进新产品,如现在要增加一种新的产品“薯条”,则无需修改原有代码,只需增加一个“薯条”产品类和一个相应的“薯条”子工厂即可。在工厂方法模式中,子工厂与产品类往往具有平行的等级结构,它们之间一一对应。

5. 工厂方法模式应用分析

5.1 工厂方法模式适用情形

  ◊ 当一个类不知道它所必须创建的对象的类信息的时候

  ◊ 当一个类希望由它来指定它所创建的对象的时候

  ◊ 当类将创建对象的职责委托给多个辅助子类中的某一个,并且希望将哪一个辅助之类是代理者这一信息局部化的时候

5.2 工厂方法模式特点

  ◊ 使用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活

  ◊ 工厂方法模式通过面向对象的手法,将所要创建的具体对象的创建工作延迟到子类,从而提供了一种扩展的策略,较好的解决了紧耦合的关系

  ◊ 工厂方法模式遵守依赖倒置原则(Dependency Inversion Principle,DIP)

5.3 工厂方法模式与简单工厂模式区别

  ◊ 工厂方法模式和简单工厂模式在结构上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体工厂类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。

  ◊ 工厂方法模式退化后可以变得很像简单工厂模式。如果非常确定一个系统只需要一个具体工厂类,那么就不妨把抽象工厂类合并到具体的工厂类中去。由于只有一个具体工厂类,所以不妨将工厂方法改成为静态方法,这时候就得到了简单工厂模式

5.4 工厂方法模式与抽象工厂模式区别

工厂方法模式 抽象工厂模式
只有一个抽象产品类(Product) 有多个抽象产品类(AbstractProductA、AbstractProductA)

具体工厂类只能创建一个具体产品类的实例。

ConcreteFactoryA生产ConcreteProductA,ConcreteFactoryB生产ConcreteProductB

具体工厂类可以创建多个具体产品类的实例。

ConcreteFactory1生产ConcreteProductA1、ConcreteProductB1,ConcreteFactory2生产ConcreteProductA2、ConcreteProductB2

C#设计模式系列:工厂方法模式(Factory Method)的更多相关文章

  1. 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

    原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...

  2. 设计模式-03工厂方法模式(Factory Method Pattern)

    插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...

  3. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  4. 二十四种设计模式:工厂方法模式(Factory Method Pattern)

    工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...

  5. 设计模式之工厂方法模式(Factory Method Pattern)

    一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...

  6. 设计模式之 - 工厂方法模式 (Factory Method design pattern)

    1. 模式意图:  定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...

  7. 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源

    概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...

  8. 工厂方法模式-Factory Method(Java实现)

    工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...

  9. 浅谈C++设计模式之工厂方法(Factory Method)

    为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...

  10. PHP 设计模式系列 —— 工厂方法模式(Factory Method)(转)

    1.模式定义 定义一个创建对象的接口,但是让子类去实例化具体类.工厂方法模式让类的实例化延迟到子类中. 2.问题引出 框架需要为多个应用提供标准化的架构模型,同时也要允许独立应用定义自己的域对象并对其 ...

随机推荐

  1. 添加ssh key

    我现在根据<github入门和实践>来去摸索github 其实,我发现自己在看github时,感觉不适应,是因为自己太久没有碰到英文了.可以联想到以前当看到一个网页,根据汉字的标题或描述, ...

  2. jQuery的选择器中的通配符

    (1)通配符: $("input[id^='code']");//id属性以code开始的所有input标签 $("input[id$='code']");// ...

  3. Visual Studio 2013执行项目报错:HTTP 错误 500.22

    转至:http://www.codingwhy.com/410.html 具体报错 HTTP 错误 500.22 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ...

  4. Android与H5交互

    1.初始化WebView控件 webView = (WebView) findViewById(R.id.webview); 2.设置WebView属性 WebSettings webSettings ...

  5. STM32之待机唤醒

    前段时间我稍微涉及节能减排大赛..倡导节能的社会..没错了.你真是太聪明了..知道了我今天要讲关于STM32节能方面的模块..没错..这标题已经告诉你了是吧..哦,对,标题有写..所以..言归正传.至 ...

  6. [IOS] 'Double' is not convertible to 'CGFloat'

    在做一个对象旋转的时候,要求转动的弧度角, 这个地方报错,如题的错误,其实是类型转换的问题,swift不能静静的做类型转换,一定要显式的转换 typeTableView?.transform=CGAf ...

  7. 不能链接云服务器mysql

    如果报host'' 不允许连接MySQL服务器  1130 错误的话如果你的3306端口打开了,也把user 里的host改为% 还是不行的话,请记得更改 站点域名设置,和你服务器相同,端口一致.

  8. 学习 React(jsx语法) + es2015 + babel + webpack

    视频学习地址: http://www.jtthink.com/course/play/575 官方地址 https://facebook.github.io/react/ 神坑: 1.每次this.s ...

  9. centos执行yum出现Could not retrieve mirrorlist错误

    具体错误见截图 刚开始以为是DNS配置错误,经检查发现DNS与物理机的DNS配置是一样的,物理机可以解析DNS 搜索资料发现是/etc/nsswitch.conf这个文件的问题 这个文件hosts标签 ...

  10. for循环中的占位 pass