博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
工厂模式
阅读量:4319 次
发布时间:2019-06-06

本文共 6324 字,大约阅读时间需要 21 分钟。

简单工厂模式,工厂方法模式,抽象工厂模式

本文使用C#和Vuejs对简单工厂模式,工厂方法模式,抽象工厂模式进行了描述

分类: 创建型模式

参见

简单工厂模式

定义

  • 该模式又被称为静态工厂方法模式;
  • 简单工厂模式是由一个工厂对象决定创建出哪一种产品的实例;
  • 简单工厂模式就是可以根据传入的参数的不同,返回不同的对象;
  • 设计模式中的工厂模式借鉴了现实生活中工厂的概念。

示例

// 抽象汽车类, 也可以是接口public abstract class Car {     public string Type { get; set;}}// 特斯拉public class Tesla: Car {     public Tesla ()    {        this.Type = "电动力车";        Console.Writeline("生产特斯拉电动汽车");    }}// 奔驰public class Benz: Car {     public Benz ()    {        this.Type = "汽油动力车";        Console.WriteLine("生产奔驰汽车");    }}// 工厂public class CarFactory{    // 静态工厂方法    public static Car Build(string carName)    {        Car car = null;        if ("Tesla" == carName)        {            car = new Tesla();        } else if ("Benz" == carName)        {            car = new Benz();        } else         {            Console.WriteLine("没找到要生产的汽车Name");        }        return car;    }}// 消费者public class Customer{    public static void Main(String[] args)    {        CarFactory.Build("Benz");        CarFactory.Build("Tesla");        CarFactory.Build("Audi");    }}

JavaScript 示例

var CarFactory = (function () {    var Car = function (carName, carType) {        this.CarName = carName;        this.CarType = carType;    };    return function (carName, carType) {        return new Car(carName, carType);    }})();// 消费var audi = new CarFactory("Audi", "汽油车");var benz = new CarFactory("Benz", "汽油车");var tesla = new CarFactory("Tesla", "电动车");

Vuejs 示例

    

优点

  • 将类实例化的操作与“使用”操作分离开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端(消费者)代码中显式指定,实现了解耦;也就是说,使用者可以直接消费产品而无需知道其生产的细节
  • 把初始化实例时的工作放到工厂里进行,使代码更容易维护
  • 更符合面向对象的原则 -> 面向接口编程

缺点

  1. 如果需要新的产品,只能加if-else或者Switch加case,也就是硬编码,违反了开闭原则,对维护和扩展不够友好,所以一般使用在条件不多变化不大的情况下。
  2. 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
  3. 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构;

使用场景

  1. 工厂类负责创建的对象比较少,不会造成工厂方法中的业务逻辑太过复杂
  2. 客户端只知道传入工厂类的参数,对于如何创建对象并不关心

工厂方法模式

定义

工厂方法模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现

示例

// 抽象汽车类, 也可以是接口public abstract class Car {     public string Type { get; set;}}// 特斯拉public class Tesla: Car {     public Tesla ()    {        this.Type = "电动力车";        Console.Writeline("生产特斯拉电动汽车");    }}// 奔驰public class Benz: Car {     public Benz ()    {        this.Type = "汽油动力车";        Console.WriteLine("生产奔驰汽车");    }}// 工厂接口public interface ICarFactory{    public Car Build();}public class BenzFactory: ICarFactory{    public Car Build()    {        return new Benz();    }}public class TeslaFactory: ICarFactory{    public Car Build()    {        return new Tesla();    }}// 消费者public class Customer{    public static void Main(String[] args)    {        ICarFactory factory = null;        Car teslaCar = null;        Car benzCar = null;        // 生产 Tesla        factory = new TeslaFactory();        teslaCar = facotry.Build();        // 生产 Benz        factory = new BenzFactory();        benzCar = factory.Build();    }}

Vuejs 示例

    

优点

  1. 符合开闭原则,容易扩展,新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可;
  2. 符合单一职责原则,每个具体工厂类只负责创建对应的产品;

    缺点

  3. 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
  4. 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度;
  5. 虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
  6. 一个具体工厂只能创建一种具体产品;

    讨论

    既然是一个工厂对应一个目标对象,那我还要工厂干嘛,我直接 new 我的目标对象不就可以了

思考以下场景:

假如我有三个对象

Car car1 = new Tesla();Car car2 = new Tesla();Car car3 = new Tesla();

那么此时我不想要 Tesla 了,我想换成Benz,此时是不是需要修改三处(可能分散在系统各个类库里),这个时候工厂方法模式的好处在哪里体现呢?

CarFactory factory = new TeslaFactory();Car car1 = factory.build();Car car2 = factory.build();Car car3 = factory.build();

这个时候,要换成Benz, 就修改

CarFactory factory = new BenzFactory();

一处就可以了。

别忘了,你在加 Teacher 的时候,是符合开闭原则的,而简单工厂模式是不符合的。

使用场景

  1. 客户端不知道它所需要的对象的类。客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;
  2. 抽象工厂类通过其子类来指定创建哪个对象。对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象

抽象工厂模式

定义

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类

抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品;
抽象工厂模式主要能实现很多不同的类的修改。

示例

// 产品抽象接口public interface IProduct {}// 车 抽象接口public interface ICar: IProduct {}// 自行车 抽象接口public interface IBike: IProduct {}// 具体产品 - 特斯拉电动车public class TeslaCar: ICar {    public TeslaCar ()    {        Console.WriteLine("生产 Tesla 电动车");    }}// 具体产品 - 特斯拉自行车public class TeslaBike: IBike {    public TeslaBike ()    {        Console.WriteLine("生产 Tesla 自行车");    }}// 具体产品 - 奔驰汽车public class BenzCar: ICar {    public BenzCar ()    {        Console.WriteLine("生产 奔驰 汽油车");    }}// 具体产品 - 奔驰自行车public class BenzBike: IBike {    public BenzBike ()    {        Console.WriteLine("生产 奔驰 自行车");    }}// 抽象工厂public interface IProductFactory{    ICar BuildCar ();    IBike BuildBike ();}// 具体工厂类 - 特斯拉工厂public class TeslaProductFactory: IProductFactory{    public ICar BuildCar ()    {        return new TeslaCar();    }    public IBike BuildBike ()    {        return new TeslaBike();    }}// 具体工厂类 - 奔驰工厂public class BenzProductFactory: IProductFactory{    public ICar BuildCar ()    {        return new BenzCar();    }    public IBike BuildBike ()    {        return new BenzBike();    }    }// 消费者public class Customer{    public static void Main()    {        IProductFactory factory = null;        factory = new TeslaProductFactory();        var car = factory.BuildCar();        var bike = factory.BuildBike();        /*            当要修改产品,比如我们不要特斯啦的产品了,我要奔驰的,那么就只需要改动一个地方            factory = new TeslaProductFactory(); => factory = new BenzProductFactory();            其他地方不需要修改        */    }}

结果

生产 Tesla 电动车生产 Tesla 自行车生产 奔驰 汽油车生产 奔驰 自行车

Vuejs 示例

    

讨论

每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式针对的是多个产品等级结构。有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。总结一下我认为可以应用到抽象工厂模式的实际例子:

  1. 两种产品:特斯拉和奔驰,两种产品等级:车和自行车
  2. 两种产品:PC和MAC,两种产品等级:RAM,CPU
  3. 两种产品:水果和蔬菜,两种产品等级:南方特产,北方特产
  4. 两种产品:男人和女人,三种产品等级:黄种人,黑人,白人

就类似这种结构的对象关系都可以用抽象工厂模式来构造。。。。。

优点

  1. 分离接口和实现
  2. 切换产品族变的异常方便

    缺点

  3. 如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类;比如增加一个滑板车(特斯拉滑板车,奔驰滑板车)

    使用场景

    为创建一组对象提供了一种解决方案

总结

  • 简单工厂模式
    简单工厂类负责了所有产品的创建逻辑,当需要引进一个新的产品时,就不得不修改工厂类的产品创建逻辑,当产品类型较多时有可能造成工厂类的产品创建逻辑过于复杂,不利于系统的维护和扩展
  • 工厂方法模式
    对简单工厂模式的设计优化,简单工厂模式中如果新增一类产品,就需要修改工厂静态方法的产品创建逻辑,而使用工厂方法模式,只需要新扩展出一个新的工厂子类和产品类,使系统具有了良好的扩展性和维护性
  • 抽象工厂模式
    为创建一组(一族)对象提供了一种解决方案,与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一组(一族)产品。

本文完。

参考资料:

转载于:https://www.cnblogs.com/zanpen2000/p/7324976.html

你可能感兴趣的文章
View Controller Programming Guid for iOS 笔记
查看>>
[模板] 最大流和费用流分别的两种做法
查看>>
python 最大连续子数组的和
查看>>
Python中的闭包
查看>>
05.if else format
查看>>
如何从Eclipse官网下载我们想要的版本
查看>>
js获取spn里面的东西
查看>>
Mongodb之增删改查操作
查看>>
elasticsearch 索引,更新,增量更新,不停机修改升级 ,简单使用
查看>>
前端生成二维码图片以及条形码图片
查看>>
LA4794 分享巧克力
查看>>
《梦断代码》第四阶段阅读感想(包括第9、10、11共三章)
查看>>
OpenCV4Android 之 OpenCV4Android SDK
查看>>
serialVersionUID作用
查看>>
解决无法访问U盘打开提示拒绝访问的问题
查看>>
unicode 字符串。互相准换
查看>>
分组加密算法CBC模式的 Padding Oracle Attack 与 Hash算法的Length Extention Attack 小记...
查看>>
虚拟基类的初始化
查看>>
C++中析构函数为什么要是虚函数
查看>>
【转】记录pytty用户名和密码
查看>>