.NET泛型技巧之打造可复用的抽象工厂

技巧

  泛型不仅能用来做容器,还能够提供代码复用的手段。在泛型的参与下,许多设计就可能更精妙,更具扩展性。今天我就来演示一个利用泛型增强的抽象工厂模式。我们知道,抽象工厂(Abstract Factory)模式是将工厂和产品全部抽象化,一个抽象工厂生成一组抽象产品,而一个具体工厂则生成具体产品的一个特定组合。它能够维持这种相关对象组合的一致性,并使得用户不需要了解工厂和产品的具体实现。传统的Abstract Factory主要弱点是类型依赖性强,可复用性弱。一个抽象工厂通常是为一个特定需要而设计,通常不能被其他需要抽象工厂的场合使用。而且尽管抽象工厂可以将实际生产任务委派给特定类型的工厂,但这种委派是需要通过自己纯代码实现的,没能利用语言所提供的抽象特性。我们今天的任务就是编写一个不针对特定产品类型和数目的泛型抽象工厂,当你需要特定的抽象工厂时,可随时复用无需再定义专门的抽象工厂实现。

  我们首先从只生成一个产品的工厂方法开始,以这作为抽象工厂的原料。很明显,可以设计这样一个接口作为工厂方法的模板:

public interface IFactory<T>
{
 T Create();
}
  这个工厂生产一个T类型的对象。当你实现此工厂时,应该让T为抽象产品的类型——即产品通用的基类。比如我们可以实现一个采用无参数构造函数来创建对象的OpNewFactory实现:

public class OpNewFactory<TAbstractProduct, TProduct> : IFactory<TAbstractProduct>
where TProduct : TAbstractProduct, new()
{
 public TAbstractProduct Create()
 {
  return new TProduct();
 }
}
  从此例子可以看出,你应该仅实现抽象类型的IFactory接口,并生成具体类型。现在我们做完了单一产品的工厂方法模板,就要开始定义生产多个产品的抽象工厂接口了。.NET泛型支持按类型参数个数进行重载,就是说,我们可以定义生产一个、两个、三个……等多种数目的抽象工厂接口,而使用同一个名字。(汗吧,这就是所谓支持“任意数目”的手法)这里免不了要拷贝代码,不过别担心,纯拷贝而已,使用的时候可是非常舒心的哦。我们以生产两种产品类型的抽象工厂为例介绍。能不能定义成这样呢?

public interface IAbstractFactory<T1, T2>
{
 T1 Create();
 T2 Create(); //编译错误!!!
}
  哦不!方法不能以返回类型区分重载,只能靠参数类型重载。然而这里我们显然不能用T1和T2作为参数,因为这些方法就是为了生产T1和T2准备的,怎么能接受它们作为参数呢?难道要命名为Create1和Create2吗?这很难接受,我们希望生产方法能够体现产品的类型,怎么能叫1和2呢。为了解决这个问题,我们引入了TypeToken<T>类型,它的定义如下:

public sealed class TypeToken<T>
{
 static private TypeToken<T> instanceValue = new TypeToken<T>();
 static public TypeToken<T> Instance
 {
  get { return instanceValue; }
 }

 private TypeToken() { }
}
  这个类没有成员,并且每个类型实参只能创建一个实例,因此代价极小。但就是这小小的实例上带有其类型实参的类型信息,因此可以作为判断函数重载的依据。我们用TypeToken<T>作为区分生产函数重载的依据,实现如下:

public interface IAbstractFactory<T1, T2>
{
 T1 Create(TypeToken<T1> token);
 T2 Create(TypeToken<T2> token);
}
  现在我们针对抽象工厂实现具体工厂。具体工厂就是利用生产每种产品的单一工厂来组合实现。因此你只要有每种类型的单一工厂就可以直接组合生成抽象工厂,而无需定义一个类来做这件事。注意,对每种数目的抽象工厂接口都需要对应生成一个具体工厂的实现,这里我仅针对生成两个产品的演示:

public class ConcreteFactory<T1, T2> : IAbstractFactory<T1, T2>
{
 private IFactory<T1> factory1;
 private IFactory<T2> factory2;

 public ConcreteFactory(IFactory<T1> f1, IFactory<T2> f2)
 {
  factory1 = f1;
  factory2 = f2;
 }

 public T1 Create(TypeToken<T1> token)
 {
  return factory1.Create();
 }

 public T2 Create(TypeToken<T2> token)
 {
  return factory2.Create();
 }
}

public static class ConcretFactory
{
 public static ConcreteFactory<T1, T2> NewFactory<T1, T2>(IFactory<T1> f1, IFactory<T2> f2)
 {
  return new ConcreteFactory<T1, T2>(f1, f2);
 }
}
  注意,我又声明了一个没有类型参数的ConcretFactory类,用一个静态方法来生成泛型ConcretFactory的实例,这是因为使用泛型方法可以推测类型参数,使得我们可以不必输入尖括号或Of语句,而泛型类则没有这个功能。现在大功告成!我们用一个例子来演示这个泛型抽象工厂的工作情况。现在假设我们需要一个生产PC的抽象工厂,需要生产两种抽象产品:处理器和内存。处理器和内存的抽象和具体实现如下:

Processor 和 Ram
public abstract class Processor
{
 public abstract string Model { get; }
}

public abstract class Ram
{
 public abstract int Frequency { get;}
}

public class PentiumProcessor : Processor
{
 public override string Model
 {
  get { return "Pentium Extreme Edition 955"; }
 }
}

public class AthlonProcessor : Processor
{
 public override string Model
 {
  get { return "Athlon 64 X2 FX-60"; }
 }
}

public class DDRRam : Ram
{
 public override int Frequency
 {
  get { return 400; }
 }
}

public class DDR2Ram : Ram
{
 public override int Frequency
 {
  get { return 533; }
 }
}
  下面的代码演示了如何随心所欲生成想要的抽象工厂接口以及快速从现有单一产品工厂组合成特定的具体工厂实现。

class Program
{
 static IAbstractFactory<Processor, Ram> ComputerFactory(string type)
 {
  if (type == "Intel")
  {
   return ConcretFactory.NewFactory( new OpNewFactory<Processor, PentiumProcessor>(),
new OpNewFactory<Ram, DDR2Ram>());
  }
  else if (type == "AMD")
  {
   return ConcretFactory.NewFactory( new OpNewFactory<Processor, AthlonProcessor>(),
   new OpNewFactory<Ram, DDRRam>());
  }

  //unknown type
  return null;
 }

 static void Main(string[] args)
 {
  //Yield a computer of Intel
  IAbstractFactory<Processor, Ram> factory1 = ComputerFactory("Intel");

  Ram ram1 = factory1.Create(TypeToken<Ram>.Instance);
  Processor cup1 = factory1.Create(TypeToken<Processor>.Instance);

  Console.WriteLine("An Intel Computer");
  Console.WriteLine("CPU Model: {0}", cup1.Model);
  Console.WriteLine("Memory Frequency: {0} MHz", ram1.Frequency);

  Console.WriteLine();

  //Yield a computer of AMD
  IAbstractFactory<Processor, Ram> factory2 = ComputerFactory("AMD");

  Ram ram2 = factory2.Create(TypeToken<Ram>.Instance);
  Processor cup2 = factory2.Create(TypeToken<Processor>.Instance);

  Console.WriteLine("An AMD Computer");
  Console.WriteLine("CPU Model: {0}", cup2.Model);
  Console.WriteLine("Memory Frequency: {0} MHz", ram2.Frequency);
 }
}
  总结:

  我们用泛型技术成功地增强了原本重用性较低的抽象工厂,演示了泛型在提高抽象性和代码重用方面卓越的价值。

时间: 2024-10-31 09:10:28

.NET泛型技巧之打造可复用的抽象工厂的相关文章

六点技巧快速打造网站外链建设

大家好,我是王继顺SEO,现在大部分人都把网站优化的精力放在了网站外链上,甚至在网站优化的排名上拼的是网站的外链数量,我们不可否认的说,网站外链在网站优化中的确起到了很大的作用,毕竟网站与网站之间.网站与互联网之间靠的是链接联系在一起.因此,如何把自己网站的外链做大做强就成为了每一个操作者的梦想.但是,在外链操作上,我们也不能盲目的去发布,高效.针对性的发布外链才能最短的时间内获得最大的效益,因此,外链建设也需要有的放矢,事半功倍的操作外链.下面就分享我的六点技巧快速打造外链建设. 1.软文投稿

Microsoft FrontPage XP使用技巧-打造一个新的天堂

frontpage|技巧 网页制作是什么? 网页制作就是根据网页效果图,把它实现成浏览器中可以浏览的网页.我们已经使用过或者听别人介绍过很多的网页制作工具.FrontPage,Dreamweaver,GoLive等等这些都是我们平常所知道的网页设计软件,而FrontPage毫无疑问是一个简单易用,功能强大的网页制作工具.如今FrontPage推出了新的版本,他依旧是和Office 一起推出的,不过不同于以往的是,新版本Office系列软件不再是以年份来命名了,使用了新的命名方式,MicroSof

Photoshop彩妆技巧:打造性感双唇

技巧 Photoshop可以将模特本来色彩暗哑的双唇处理得鲜艳预滴,和我们一起打造莹彩双唇吧! 原图: 最终效果:        

适合新手的技巧 后期打造独特柔焦效果

一期一会的课堂又到了,我们一起来学习,帮助初学者.让我们有个好的学习环境掌握有效的学习方式和萃取各类技巧,我们才能学的更好.期望我的教程能在你的摄影之路上成为一块成长的垫脚石. 之前很多同学问我柔和虚化的效果如何制作,方法有很多种,同学说要一步到位的,要按一下就可以的方法,还真有. 效果就出来了. 不用插件如何打造梦幻效果呢?下面我们介绍不适用插件就能做到的方法,图片来自网络. 第一步:导入需要柔和虚化的图,在图层初复制一个图层出来. 第二步:选择滤镜-模糊-高斯模糊. 第三步:选择图层的图层模

PhotoShop给人物整容技巧,打造魔鬼身材

随着气温的逐渐上升,又到了漂亮MM们大秀身材的时节了.每个MM都想拥有魔鬼的身材,可如果她身材不够好, 拍出来的照片显得偏胖怎么办呢?不用担心,我们今天就为大家奉献三剂Photoshop瘦身的灵丹妙药! 一.瘦脸神丹 原图 效果图 PS小技巧:蒙版加自由变形工具,快速瘦脸 打开例图,本例MM的脸因为广角畸变而稍微有些显胖,不要紧,简单两步,还她迷人小脸. 1. 使用自由变形工具完成瘦脸 首先建立图层副本,按Ctrl+J复制背景层.然后,在编辑菜单中找到自由变化工具(或按Ctrl+T),拖动变形框

Win7技巧:打造得心应手的Win7任务栏

相比于XP系统,Win7的任务栏强大了不少,尤其是在个性化操作上,十分得心应手.所以,本文里,我们继续介绍一下Win7的任务栏相关的应用,希望大家都能够很好的掌握Win7任务栏. 我们可以对任务栏进行自定义,设定一个自己更加顺手和个性的任务栏,所以,这里我们仍然需要研究一个窗口--任务栏属性窗口.在这个窗口里,可以设置使用小图标.选择屏幕放置位置.任务栏按钮.通知图标.Aero Peek预览桌面.工具栏等个性化内容.操作时,鼠标右击任务栏中空白处,在右键菜单中选择属性,即可查看任务栏属性,在属性

ps文字技巧:打造简单黑白字特效

先来看看效果图: 步骤一.先打开photoshop应用程序,然后新建一个RGB白色背景.大小随意设置就我为800*600的文件.将前景色设置为黑色,背景色设置为白色即可.如图所示: 步骤二.现在在绘图区用到文字工具输入文字设置字体,输入完成后在执行"图层--栅格化图层"栅格化图层之后在按住ctrl+E将文字图层和背景图层合并在一起.如图所示: 步骤三.现在我们通过矩形工具或者套索工具来勾选一个选区,勾选之后,然后在执行"图像--调整--反向"操作即可.如下图所示:

ps文字特效技巧:打造逼真碎块熔岩字

最终效果 <图1> 1.制作文字效果之前,需要先制作一些纹理.新建一个1024 * 768像素的文件,新建一个图层,按字母键"D"把前背景颜色复位到默认的黑白,执行:滤镜 > 渲染 > 云彩,效果如下图. <图2> 2.执行:滤镜 > 像素化 > 点状化,大小设置为15,如图3,确定后按Ctrl + Shift + U 去色.然后执行:滤镜 > 模糊 > 高斯模糊,设置为8,效果如图5. <图3> <图4&g

Visual Studio技巧之打造拥有自己标识的代码模板

可能经过很多博客的介绍,大家都知道代码段的使用,使用代码段可以很方便地生成一些常用的代码格式,确实对我们开发很方便.在团队开发中或者在某些情况下我们经常可能还会希望使用Visual Studio生成的代码自动带有一些信息,比如代码文件的创建时间.代码的说明及对命名空间的引用等等,实际上这个功能经周公证实在Visual Studio2005以上版本中就支持了. 下面以周公的本本的具体情况为例来加以说明,在周公的DELL 1425上系统是安装在C盘,在系统盘下同时安装了Visual Studio 2