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. [BZOJ1562][ZJOI2007] 最大半连通子图

    Description Input 第一行包含两个整数N,M,X.N,M分别表示图G的点数与边数,X的意义如上文所述.接下来M行,每行两个正整数a, b,表示一条有向边(a, b).图中的每个点将编号 ...

  2. [翻译svg教程]Path元素 svg中最神奇的元素!

    先看一个实例 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999 ...

  3. iOS开发之单元测试

    开始之前 本文侧重讲述如何在iOS程序的开发过程中使用单元测试.使用Xcode自带的OCUnit作为测试框架. 一.单元测试概述 单元测试作为敏捷开发实践的组成之一,其目的是提高软件开发的效率,维持代 ...

  4. PHP:( && )逻辑与运算符使用说明

    第一次看到以下语句的写法大惑不解 ($mCfg['LockChinaIp']==1 && (int)$_SESSION['AdminUserId']==0 && sub ...

  5. C#窗体中读取修改xml文件

    由于之前没有操作过xml文件,尤其是在窗体中操作xml,脑子一直转不动,而且很抵制去做这个功能,终于还是突破了自己通过查询资料完成了这个功能,在此记录一下自己的成果. 功能说明:程序中存在的xml文件 ...

  6. 移动前端不得不了解的html5 head 头标签

    本文主要内容来自一丝的常用的 HTML 头部标签和百度FEX的HTML head 头标签. 移动端的工作已经越来越成为前端工作的重要内容,除了平常的项目开发,HTML 头部标签功能,特别是meta标签 ...

  7. Centos 6.5 搭建l2tp 服务端和客户端

    废话不多说直接上步骤. server #epel仓库愿安装 rpm -ivh http://mirrors.ustc.edu.cn/fedora/epel/6/x86_64/epel-release- ...

  8. MYSQL MHA

    MYSQL MHA 简介: MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于 Face ...

  9. Android 6.0 使用HttpURLConnection 使用Get提交遇到405等问题。

    HttpURLConnection 在调用connection.setDoOutput(true)之后会自动把提交方式改为POST.然后调用方法的时候有可能会出现这种情况 在调用get的时候设置为co ...

  10. 控制TextField的内容长度

    参考如下代码(下例是控制设置交易密码,控制6位): - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [ ...