前言
上一篇我们介绍了单例模式, 今天给大家讲一个比较简单的模式 -- 工厂模式 (Factory Method), 工厂模式又是什么呢? 顾名思义, 工厂 -- 生产制造东西的地方. 那么应用在程序当中该如何使用, 并且又起到什么效果呢? 以至于为什么用工厂模式呢?
之前我们说的 OCP 原则 (开放封闭原则), 对扩展开放, 对修改封闭这一原则. 在工厂模式中有极好的体现, 对对象及类进行极好的封装. 使其减少代码之间的耦合性. 更具有扩展性.
工厂模式介绍
一, 来由
在我们编程过程当中, 总会面临一些类的创建以及对象的创建, 但是由于需求而不断变动 (增加或者修改), 导致对象的变化. 这时怎么处理这个问题呢?
工厂模式提供的一种封装机制, 隔离出了那些易变动的对象. 这个时候需求的变动不再影响之前的对象的变动了.
二, 意图
定义一个用于创建对象的接口, 让子类决定实例化哪一个类. FactoryMethod 使一个类的实例化延迟到其子类.
三, 案例图
工厂模式中由以下部分组成:
(1), 抽象工厂 (Creator): 复制定义工厂所需的基本规则, 其他任何具体工厂都得继承此抽象工厂
(2), 具体工厂 (Concrete_Creator): 继承抽象工厂, 实现其定义的方法, 以此来创建具体的产品
(3), 抽象产品 (Product): 复制定义产品的基本方法及规则, 所有具体产品都得基础此抽象产品类
(4), 具体产品 (Concrete_Product): 继承抽象产品, 实现其定义抽象方法, 由具体工厂创建, 两者是一一对应的关系.
四, 工厂模式代码实现
这里我们通过一个事例来介绍工厂模式的规则及用法. 在工厂模式中, 定义抽象工厂, 然后其具体工厂继承实现其抽象方法调用继承了抽象产品类的具体产品来创建产品.
下面我们就手机产品的制造来看看下面的事例吧:
- namespace ConsoleApp4
- {
- public class Factory_Method_Pattern
- {
- }
- #region 产品 =========================
- /// <summary>
- /// 抽象手机产品类
- /// </summary>
- public abstract class Phone
- {
- public abstract string Create();
- }
- /// <summary>
- /// 具体华为手机产品类
- /// </summary>
- public class Huawei : Phone
- {
- /// <summary>
- /// 实现抽象方法
- /// </summary>
- /// <returns></returns>
- public override string Create()
- {
- return "华为一号现世";
- }
- }
- /// <summary>
- /// 具体小米手机产品类
- /// </summary>
- public class Xiaomi : Phone
- {
- /// <summary>
- /// 实现抽象方法
- /// </summary>
- /// <returns></returns>
- public override string Create()
- {
- return "小米一号现世";
- }
- }
- #endregion
- #region 工厂 =========================
- /// <summary>
- /// 抽象工厂类
- /// </summary>
- public abstract class Factory
- {
- /// <summary>
- /// 抽象工厂类的方法, 创建调用产品
- /// </summary>
- /// <returns></returns>
- public abstract Phone CreatePhone();
- }
- /// <summary>
- /// 具体华为工厂类, 继承抽象工厂类
- /// </summary>
- public class HuaweiFactory : Factory
- {
- /// <summary>
- /// 实现继承方法
- /// </summary>
- /// <returns></returns>
- public override Phone CreatePhone()
- {
- return new Huawei();
- }
- }
- /// <summary>
- /// 具体小米工厂类, 继承抽象工厂类
- /// </summary>
- public class XiaomiFactory : Factory
- {
- /// <summary>
- /// 实现继承方法
- /// </summary>
- /// <returns></returns>
- public override Phone CreatePhone()
- {
- return new Xiaomi();
- }
- }
- #endregion
- }
- class Program
- {
- static void Main(string[] args)
- {
- // 初始化工厂
- Factory huaweiFactory = new HuaweiFactory();
- // 生产具体的华为手机
- var result=huaweiFactory.CreatePhone();
- // 华为手机现世
- var answer = result.Create();
- Console.WriteLine(answer);
- Factory xiaomiFactory = new XiaomiFactory();
- result = xiaomiFactory.CreatePhone();
- answer = result.Create();
- Console.WriteLine(answer);
- Console.ReadLine();
- }
- }
在上述事例中, 同样是先把手机抽象出一个抽象类, 手机当然也不是凭空出现的. 所以需要再抽象一个工厂类. 工厂类派生子类不同的手机厂商类. 同样手机也派生了不一样的品牌. 手机厂商类再对应手机品牌去生产相应的手机. 这时我们需要增加一个手机手机品牌, 我们不需要去修改工厂类及产品类. 我们另外新增即可. 完全不影响其原来的运行. 比如我们需要新增魅族手机.
- #region 新增魅族手机 ================
- /// <summary>
- /// 新增魅族工厂类
- /// </summary>
- public class MeizuFactory : Factory
- {
- public override Phone CreatePhone()
- {
- return new Meizu();
- }
- }
- /// <summary>
- /// 新增具体魅族手机产品类
- /// </summary>
- public class Meizu : Phone
- {
- public override string Create()
- {
- return "魅族一号现世";
- }
- }
- #endregion
在客户端调用时增加以下调用就可以了
- Factory meizuFactory = new MeizuFactory();
- result = meizuFactory.CreatePhone();
- answer = result.Create();
- Console.WriteLine(answer);
使用场景及优缺点
在此模式中, 将所有要创建的具体对象的工作都延迟放在了子类中去实现, 实现了一种扩展的策略. 与 OCP 原则相对应.
工厂模式主要针对解决的是 "单个对象" 的问题. 隔离类的对象的使用者与具体类型之间的耦合关系. 去实现了一定程度的解耦.
(一) 使用场景
1, 当用户不需要知道产品的类名的时候或者不关心如何创建的时候. 我们只需要知道创建它的具体工厂的时候.
2, 将创建对象的任务委托给多个工厂中的一个, 客户端使用的时候无需关心是哪一个创建产品. 当需要动态指定.
(二) 优点
1, 在编程方法中, 客户端调用不需要知道产品的具体工厂, 也不需要关心如何创建的.
2, 在增加需求的时候, 增加产品的时候仅需要新增一个工厂类及产品类即可, 不需要对原来的代码进行修改. 可轻易的扩展.
(三) 缺点
在增加产品的时候, 额外的增加了工厂类及产品类. 增加一个产品增加两个类. 在一定程度上增加了系统的复杂度. 同时也增强了类之间的依赖性. 这也就是其中不好的问题
总结
每一个设计模式都有对应的使用场合, 切勿滥用. 在我们学习设计模式的同时, 我们也需要以其原主要则作为基准学习. 万万不能违背原则. 在设计模式 -- 工厂模式中, 将创建对象的任务委托给其工厂子类, 延迟执行. 解决了系统难于扩展的问题, 同时也减少了具体类与对象之间的耦合性. 也实现了开放扩展封闭修改的原则.
这个社会是存在不公平的, 不要抱怨, 因为没有用! 人总是在反省中进步的!
C# 设计模式系列目录
欢迎大家扫描下方二维码, 和我一起踏上设计模式的闯关之路吧!
来源: https://www.cnblogs.com/hulizhong/p/11404514.html