C#设计模式系列:工厂方法模式(Factory Method)
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)的更多相关文章
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...
- 设计模式-03工厂方法模式(Factory Method Pattern)
插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...
- 【设计模式】工厂方法模式 Factory Method Pattern
在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...
- 二十四种设计模式:工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...
- 设计模式之工厂方法模式(Factory Method Pattern)
一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...
- 设计模式之 - 工厂方法模式 (Factory Method design pattern)
1. 模式意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...
- 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源
概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...
- 工厂方法模式-Factory Method(Java实现)
工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...
- 浅谈C++设计模式之工厂方法(Factory Method)
为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...
- PHP 设计模式系列 —— 工厂方法模式(Factory Method)(转)
1.模式定义 定义一个创建对象的接口,但是让子类去实例化具体类.工厂方法模式让类的实例化延迟到子类中. 2.问题引出 框架需要为多个应用提供标准化的架构模型,同时也要允许独立应用定义自己的域对象并对其 ...
随机推荐
- 基于ThinkPHP3的微信平台开发_1
微信公众平台是个好东西,具体的就不说了,我直接说技术>_< 下图为目录结构一览: 微信开发 - 文件目录结构 平台功能: 此次开发的平台是面向多微信公众号.微信多公众号主(下面简称号主)的 ...
- Android SDK Manager 更新代理配置
转自:http://www.cnblogs.com/tao560532/p/4483067.html 出现问题: 消除SDK更新时,有可能会出现这样的错误:Download interrupted: ...
- T-SQL Recipes之Separating elements
Separating elements Separating elements is a classic T-SQL challenge. It involves a table called Arr ...
- WPF-禁止二次启动
App.xaml.cs protected override void OnStartup(StartupEventArgs e) { //禁止二次启动 this.Startup += new Sta ...
- bootstrap学习笔记【转】
bootstrap是由Twitter公司研发的一个基于HTML,CSS,JavaScript的开源框架,最重要的部分是它的响应式布局.(国内文档翻译官网:http://www.bootcss.com/ ...
- JSON数据和对象
在js中像数字类型.字符串类型.布尔类型这些都不能再被拆分,属于基本类型.与之相对有一种复杂类型:对象类型,它是本身由多个其他类型组合而成的. 创建对象有两种方法,一.new Object()创建一个 ...
- Lua游戏时区问题
关于cocos2dx-lua版本中游戏时间显示问题 2015-04-19 19:07 1466人阅读 评论(0) 收藏 举报 分类: Lua(29) cocos2d(38) 版权声明:本文为博 ...
- Java中堆内存和栈内存详解
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
- linux用户管理(二)
最简单的加入用户useradd 用户名这样的命令不好,因为会新建一个组为这个用户. 这里提到一个问题,为什么普通用户没有/etc/shadow的写权限却能修改自己的密码呢. 因为 /user/bin/ ...
- For循环打印正三角,倒三角,菱形
A:正三角形: 内循环的判断条件:y<=x for(int x=0; x<5; x++) { for(int y=0; y<=x; y++) { System.out.print(& ...