Loading

设计模式之工厂模式

工厂模式定义

工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

代理模式结构图和实现

结构图

image-20210701230045777

实现方式

  1. 让所有产品都遵循同一接口。 该接口必须声明对所有产品都有意义的方法。
  2. 在创建类中添加一个空的工厂方法。 该方法的返回类型必须遵循通用的产品接口。
  3. 在创建者代码中找到对于产品构造函数的所有引用。 将它们依次替换为对于工厂方法的调用, 同时将创建产品的代码移入工厂方法。 你可能需要在工厂方法中添加临时参数来控制返回的产品类型。
  4. 为工厂方法中的每种产品编写一个创建者子类, 然后在子类中重写工厂方法, 并将基本方法中的相关创建代码移动到工厂方法中。

代码实现

这里还是拿之前简单工厂模式那个栗子来做

首先我们先创建一个运算类的父类

定义两个属性以及一个获取结果的虚方法

public class Operation
    {
        public double NumA { get; set; }

        public double NumB { get; set; }

        public virtual double GetResult()
        {
            double result = 0;
            return result;
        }
    }

接着,创建一个工厂接口,这个接口目的就是为了让派生类来决定到底要实例化哪一个运算子类

interface IFactory
    {
        Operation CreateOperation();
    }

然后去创建几个派生自运算基类的具体运算类,如假发、减法等具体实现类

 public class OperationAdd : Operation
    {
        public override double GetResult()
        {
            return NumA + NumB;
        }
    }
    
    .....

再去构建对应的工厂方法,继承自工厂接口

 public class AddFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationAdd();
        }
    }

最后,客户端调用,这里写的有点烂,别介意,看主要的就行

IFactory factory;
                Operation operation = null;
                switch (oper)
                {
                    case "+":
                        factory = new AddFactory();
                        operation = factory.CreateOperation();
                        operation.NumA = Convert.ToDouble(num1);
                        operation.NumB = Convert.ToDouble(num2);
                        break;
                    case "-":
                        factory = new SubFactory();
                        operation = factory.CreateOperation();
                        operation.NumA = Convert.ToDouble(num1);
                        operation.NumB = Convert.ToDouble(num2);
                        break;
                    default:
                        break;
                }

可以发现,我们在实例工厂接口时,并没有直接去实例化工厂接口,而是实例化它的派生类,然后再实例化运算具体实现类,通过factory.CreateOperation();让它自己去找对应的工厂类,而不同的工厂类里面又去实例化了对应的运算方法,最终就是通过调用operation.GetResult()取到运算结果

工厂模式优缺点

优点

  • 可以避免创建者和具体产品之间的紧密耦合。
  • 单一职责原则。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
  • 开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

缺点

  • 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。
  • 而且可能还会存在大量分支判断等

工厂模式使用场景

1、当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。

工厂方法将创建产品的代码与实际使用产品的代码分离, 从而能在不影响其他代码的情况下扩展产品创建部分代码。

例如, 如果需要向应用中添加一种新产品, 你只需要开发新的创建者子类, 然后重写其工厂方法即可。

2、 如果你希望用户能扩展你软件库或框架的内部组件****, 可使用工厂方法****。

继承可能是扩展软件库或框架默认行为的最简单方法。 但是当你使用子类替代标准组件时, 框架如何辨识出该子类?

解决方案是将各框架中构造组件的代码集中到单个工厂方法中, 并在继承该组件之外允许任何人对该方法进行重写。

3、如果你希望复用现有对象来节省系统资源****, 而不是每次都重新创建对象****, 可使用工厂方法****。

在处理大型资源密集型对象 (比如数据库连接、 文件系统和网络资源) 时, 你会经常碰到这种资源需求。

简单工厂与工厂模式有什么区别?

简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端选择的条件去实例化相关的类,对于客户端来说,去除了与具体产品的依赖,使得客户端无需过多关系底层的具体实现。而在使用工厂方法模式实现时,客户端需要决定到底去实例化哪一个工厂类,大量的罗技分支判断可能还是存在的。简单来说就是把那些判断又搬到了客户端,如果想要扩展新功能,就只需要去创建相关的类和工厂,达到了开闭原则和单一职责原则,但也会使得代码层次可能有点繁杂和冗余。

示例源代码

代码仓库地址:https://github.com/luchong0813/DesignModel

posted @ 2021-07-01 23:23  傲慢与偏见luc  阅读(75)  评论(0编辑  收藏  举报