zoukankan      html  css  js  c++  java
  • c# 设计模式 之:简单工厂、工厂方法、抽象工厂之小结、区别

    转载自:https://www.cnblogs.com/25miao/p/10389616.html

    很多时候,我发现这三种设计模式难以区分,常常会张冠李戴闹了笑话。很有必要深入总结一下三种设计模式的特点、相同之处和不同之处。

    1 本质

      三个设计模式名字中都含有“工厂”二字,其含义是使用工厂(一个或一系列方法)去生产产品(一个或一系列类的实例)

      另外,有时候,我们常常会将生产产品的一个或一系列方法封装到一个类中,我习惯把这个类叫做“工厂类”;而被实例化的类称作“产品类”。

    2 简单工厂

          简单工厂模式是类的创建性模式,又叫做静态工厂方法模式。就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例

         一般涉及到三种角色:
            工厂类:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体的类实现。
            抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。
            具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,由具体类实现。

      工厂类(SimpleFactory)拥有一个工厂方法(create),接受了一个参数,通过不同的参数实例化不同的产品类。

      如下边UML类图所示为简单工厂。  

      

          以园丁种植水果为例讨论该模式的具体实现:
             Fruit 水果接口,规定水果具有的一些共同特性
             Apple 苹果类 派生自Fruit接口
             Strawberry 草莓类 派生自Fruit接口
             FruitGardener 园丁类 负责草莓与苹果的创建工作。
             当Client要创建水果(苹果或草莓对象)的时候调用园丁类的factory方法创建:

            

      1 Fruit.cs
      2 namespace Simple_Factory
      3 {
      4     public interface Fruit
      5     {
      6         //生长
      7         void grow();
      8         //收获
      9         void harvest();
     10         //种植
     11         void plant();
     12     }
     13 }
     14 
     15 Apple.cs
     16 namespace Simple_Factory
     17 {
     18     public class Apple : Fruit
     19     {
     20         public Apple()
     21         {
     22         }
     23         #region Fruit 成员
     24         public void grow()
     25         {
     26             Console.WriteLine("Apple is growing.......");
     27         }
     28         public void harvest()
     29         {
     30             Console.WriteLine("Apple is harvesting.......");
     31         }
     32         public void plant()
     33         {
     34             Console.WriteLine("Apple is planting.......");
     35         }
     36         #endregion
     37     }
     38 }
     39 Strawberry.cs
     40 namespace Simple_Factory
     41 {
     42     public class Strawberry : Fruit
     43     {
     44         public Strawberry()
     45         {
     46         }
     47         #region Fruit 成员
     48         public void grow()
     49         {
     50             Console.WriteLine("Strawberry is growing.......");
     51         }
     52         public void harvest()
     53         {
     54             Console.WriteLine("Strawberry is harvesting.......");
     55         }
     56         public void plant()
     57         {
     58             Console.WriteLine("Strawberry is planting.......");
     59         }
     60         #endregion
     61     }
     62 }
     63 FruitGardener.cs
     64 namespace Simple_Factory
     65 {
     66     public class FruitGardener
     67     {
     68         //静态工厂方法
     69         public static Fruit factory(string which)
     70         {
     71             if (which.Equals("Apple"))
     72             {
     73                 return new Apple();
     74             }
     75             else if (which.Equals("Strawberry"))
     76             {
     77                 return new Strawberry();
     78             }
     79             else
     80             {
     81                 return null;
     82             }
     83         }
     84     }
     85 }
     86 Client.cs
     87 namespace Simple_Factory
     88 {
     89     class Client
     90     {
     91         static void Main(string[] args)
     92         {
     93             Fruit aFruit = FruitGardener.factory("Apple");//creat apple
     94             aFruit.grow();
     95             aFruit.harvest();
     96             aFruit.plant();
     97             aFruit = FruitGardener.factory("Strawberry");//creat strawberry
     98             aFruit.grow();
     99             aFruit.harvest();
    100             aFruit.plant();
    101         }
    102     }
    103 }
    104 输出如下:
    105 Apple is growing.......
    106 Apple is harvesting.......
    107 Apple is planting.......
    108 Strawberry is growing.......
    109 Strawberry is harvesting.......
    110 Strawberry is planting.......                        

              简单工厂模式的核心是工厂类,这个类负责产品的创建,而客户端可以免去产品创建的责任,这实现了责任的分割。但由于工厂类集中了所有产品创建逻辑的,如果不能正常工作的话会对系统造成很大的影响。如果增加新产品必须修改工厂角色的源码。 

              优点:

        (1)很明显,简单工厂的特点就是“简单粗暴”,通过一个含参的工厂方法,我们可以实例化任何产品类,上至飞机火箭,下至土豆面条,无所不能。所以简单工厂有一个别                          名:上帝类。

        缺点:

        (1)任何”东西“的子类都可以被生产,负担太重。当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。

        (2)在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,无能为力。因为增加新产品只能通过修改工厂方法来实现。

      工厂方法正好可以解决简单工厂的这两个缺点。

    3 工厂方法

      工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。

      如下边UML类图所示为工厂方法。

      

      优点:

        (1)工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产;(对应简单工厂的缺点1)

        (2)同时增加某一类”东西“并不需要修改工厂类,只需要添加生产这类”东西“的工厂即可,使得工厂类符合开放-封闭原则。

      缺点:

        (1)相比简单工厂,实现略复杂。

        (2)对于某些可以形成产品族的情况处理比较复杂。

      对于缺点(2),我们可以借用抽象工厂来实现。

    4 抽象工厂

      抽象工厂是应对产品族概念的。

      例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车看作是另一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,而是一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的“抽象”指的是就是这个意思。

      上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。

      如下边UML类图所示为抽象工厂。

      

      优点:针对产品族;

      缺点:针对产品族。

      所以,只有对应产品族的情况下,才需要使用抽象工厂模式。

    5 区别

      简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)

      工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)   

      抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)  

    6 注意事项

      (1)工厂类常常采用单例模式(Singleton)。

      (2)工厂类拥有基类(定义共同接口),基类可以为纯虚类,也可以定义缺省方法。

      (3)对于工厂方法和抽象工厂,基类中的生产产品的函数常常为虚函数,以实现动态绑定。

      (4)调用工厂方法的函数通常采用工厂实现的指针和引用作为形参,以便根据不同的工厂实参调用不同的工厂方法。

  • 相关阅读:
    访问静态文件时, 为NetCore项目添加MIME类型支持
    Ant design pro formItem validator报警告 `callback` is deprecated. Please return a promise instead.
    .NET Core 自定义过滤器 AllowAnonymous 失效问题
    前端获取二进制流下载文件并解决无法获header问题,Content-Disposition
    cefSharp通过js操控页面,含跨域操控
    C#中Application.StartupPath和System.Environment.CurrentDirectory的区别
    C# XML配置文件读写类(用于程序配置保存)
    C#爬虫使用代理刷文章浏览量
    c#批量抓取免费代理并验证有效性
    C# 代理HTTP请求
  • 原文地址:https://www.cnblogs.com/shiding/p/14527050.html
Copyright © 2011-2022 走看看