zoukankan      html  css  js  c++  java
  • 抽象工厂的一个范例

    设计模式中的抽象工厂是这样一种方式:它提供一个接口,以创建多个相关联的对象,而无需具体指定其具体的类。形象地说,它是一个工厂,能够生产众多产品。当用户需要某种产品的时候,不需要去关心这个产品的具体实现,而只需要指定产品的名称,抽象工厂就能够按你的要求进行生产。这里所指的产品,在C#中我们代表的是一个实例的类。

    在面向对象的程序设计中,我们经常会定义许多类,并通过new对其进行实例化。一旦类对象较多,且在实例化的时候,要做的初始化工作比较复杂的时候,我们就可以通过抽象工厂来管理。根据对象的性质和内容分别抽象成类,同时定义接口和接口方法。一旦定义了抽象工厂,实例类的工作就交给工厂,使用者只需要告诉工厂,你实例化的对象是什么就行了。

    下面我们定义了一个“音像工厂”,工厂的产品有CD和DVD。而且根据audio和Vidio又分别对CD和VCD进行了分类。假设我们把CD和DVD都看成是AVDevice,那么有关CD和DVD的类就可以抽象成一个接口:IAVDevice。这个接口要实现的方法是获得产品的音频和视频。

    现在有两个对象CD和DVD,他们又有共同的性质Audio和Video。显然我们应该将CD和DVD定义成类,而将Audio和Video定义为接口。(我们可以将接口看做为同一性质对象的分类。凡是具有相同性质的对象都实现该接口)。因为CD和DVD都属于一种AVDevice,因此它们都实现IAVDevice接口是毫无疑问的。但他们是否也应实现IAudio和IVidio接口呢?答案是肯定的,但是如此定义层次比较混乱,所以最好再为CD和DVD分别定义不同的类对象,来实现这两个接口。最后的定义如下:

    public interface IAVDevice
     {     
      IAudio GetAudio();
      IVideo GetVideo();
     }             

     public interface IVideo
     {     
      string GetPictureQuality();
     }

     public interface IAudio
     {     
      string GetSoundQuality();
     }

     class CCd:IAVDevice
     {
      public IAudio GetAudio()
      {
       return new CCdAudio();
      }
      public IVideo GetVideo()
      {
       return new CCdVideo();
      }     
     }

     class CDvd:IAVDevice
     {
      public IAudio GetAudio()
      {
       return new CDvdAudio();
      }
      public IVideo GetVideo()
      {
       return new CDvdVideo();
      }     
     }

     class CCdAudio:IAudio
     {     
      public string GetSoundQuality()
      {
       return "CD Audio is better then DVD Audio";
      }
     }

     class CCdVideo:IVideo
     {
      public string GetPictureQuality()
      {
       return "CD video quality is not as good as DVD";
      }
     }

     class CDvdAudio:IAudio
     {
      public string GetSoundQuality()
      {
       return  "DVD Audio is not as good as CD Audio";
      }     
     }

     class CDvdVideo:IVideo
     {     
      public string GetPictureQuality()
      {
       return "DVD video quality is better then CD";
      }
     }

    结构如图:


    然后,我们要实现一个机制:就是能够根据用户的要求“生产”出相应的产品,是CD还是DVD?

    class CAVMaker
     {     
      public IAVDevice AVMake(string xWhat)
      {
       switch (xWhat.ToLower())
       {
        case "cd":
         return new CCd();
        case "dvd":
         return new CDvd();
        default:
         return new CCd();                     
       }
      }

     }

    现在我们可以看它的执行流程:当我们输入”cd”时,CAVMaker就实例CCD类对象。(注意返回的结果类型为IAVDevice)。实际上得到结果相当于执行如下代码:

    IAVDevice  objFac = new CCd();

    如果我们对objFac分别调用GetAudio()和GetVideo()方法时,又会根据objFac对象的类型(它属于CCd类)实例化CCdAudio和CCdVideo类对象。(注意返回的类型),此时相当于执行如下代码:

    IAudio objAudio = new CCdAudio();
    IVideo objVideo = new CCdVideo();

    此时我们就可以再调用他们各自的方法了。

    使用以上接口和类的代码如下:
    public class AbstractFactory
     {
      static void Main(string[] args)
      {
       CAVMaker objFactMaker = new CAVMaker();
       IAVDevice objFact;
       IAudio objAudio;
       IVideo objVideo;
       string strWhat;
       strWhat = args[0];
       objFact = objFactMaker.AVMake(strWhat);
       objAudio = objFact.GetAudio();
       objVideo = objFact.GetVideo();
       Console.WriteLine(objAudio.GetSoundQuality());
       Console.WriteLine(objVideo.GetPictureQuality());
      }
     }

    执行时,将编译后的EXE文件运行,同时在命令行输入“cd“或“dvd“就可以得到不同的结果。通过这个例子,我们可以对抽象工厂有一个初步的认识。

    注:本文采用www.c-sharpcorner.com中一篇文章上的一个示例,我对它进行了简单的分析。

  • 相关阅读:
    .NET开源工作流RoadFlow-表单设计-组织机构选择
    .NET开源工作流RoadFlow-表单设计-按钮
    .NET开源工作流RoadFlow-表单设计-标签(label)
    git客户端使用
    简单几句概括join
    算法笔记:线段树
    通常情况下的中国剩余定理
    NOIP2016:Day2解题报告
    关于jzyzoj——P1341:被污染的牛奶的题解探讨
    关于错位排列
  • 原文地址:https://www.cnblogs.com/wayfarer/p/7742.html
Copyright © 2011-2022 走看看