当前位置: 首页 > news >正文

抽象工厂的一个范例

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

结构如图:1.jpg


然后,我们要实现一个机制:就是能够根据用户的要求“生产”出相应的产品,是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中一篇文章上的一个示例,我对它进行了简单的分析。

 

相关文章:

  • WebBrowser 和 Win Form 的关闭问题?
  • 蓝鸥Unity开发基础二——课时18 单例
  • 表示数值的字符串
  • 如何配置搜索功能
  • W3bsafe]SQLmap过狗命令的利用+教程
  • Linux的包管理工具介绍
  • Jive论坛与Spring框架
  • 实现支持文件分块多点异步上传的 Web Services 及其客户端(非Web)应用程序调用相关异步执行的 Web Method...
  • delphi提示错误行号之Assert(断言)
  • 转贴一篇友情提示
  • CDH5.3配置Kerberos+LDAP+Sentry记录
  • 未来通信构想 LifeWorks无缝通信
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • mysql5.7 多级主从+multisource
  • 庄子与我的名字
  • SegmentFault for Android 3.0 发布
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 345-反转字符串中的元音字母
  • ES6--对象的扩展
  • HomeBrew常规使用教程
  • iOS 系统授权开发
  • JDK 6和JDK 7中的substring()方法
  • JDK9: 集成 Jshell 和 Maven 项目.
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • nginx 配置多 域名 + 多 https
  • 对JS继承的一点思考
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 配置 PM2 实现代码自动发布
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 树莓派 - 使用须知
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 消息队列系列二(IOT中消息队列的应用)
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • (6)STL算法之转换
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (windows2012共享文件夹和防火墙设置
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET Micro Framework初体验(二)
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .Net中ListT 泛型转成DataTable、DataSet
  • .NET中使用Redis (二)
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @GetMapping和@RequestMapping的区别