C#设计模式之工厂

简介:

IronMan之工厂

前言

实用为主,学一些用得到的技术更能在如今的社会里保命。 虽然在日常的工作中设计模式不是经常的用到,但是呢,学习它只有好处没有坏处。

设计模式像是一种“标签”,它是代码编写者思想的体现。有木有感觉到这样很便捷?看到一些代码的时候就很清楚的了解编写者的思想了,这是为什么呢?因为编写者们用了“标签”,而你恰恰是知道“标签”意思的。 跟一异曲同工,在学习框架、了解框架的对象模型的时候,“标签”是时常出现,如果你不了解“标签”的意思那多痛苦啊!!!!! 还有好多,不去一一阐述了。

工作中需求的变更时常令我们头疼不已,总是要按着需求来重新的修改代码,然后发布新的产品版本,或者是出更新包。 在需求变更中,对应着代码也要修改,但是这修改也是分层次的。比如修改的模板在当初设计的时候遵循了开闭原则(OCP)的话,代码的修改就变的轻松的多了。

我想制造出一个像电影《钢铁侠》里面那样的的一身盔甲,又或者说是机器吧,我把这个想法告诉了我的朋友们,他们都认为我疯了。

好吧,我说的是用代码抽象的制造出”钢铁侠“

废话不多说,下面这个系列是用钢铁侠(IronMan)作为主题的设计模式 今天来学习简单工厂模式、工厂方法模式、以及抽象工厂模式。

问题的发现

需求:
“玩具厂”有一天找到我说:“Jin叫兽我们这需要一些部件,我们会提供“图纸”,请您帮忙制造,您看有问题吗?”。
我:“当然没有问题了。很乐意帮助你们”。
“玩具厂”:“噢!好的。Jin叫兽,时间方面还有什么问题嘛?”
我:“没问题的,我会尽快的”。
“玩具厂”:“那真的太感谢您了,Jin叫兽。我们就不打扰您了,先走了。”
我:“晚上一起吃顿饭吧”。
“玩具厂”:“Jin叫兽不必客气啊”。
我:“好,你们慢走”。

生产车间:
“一点挑战性都没有,随随便便就制造出来了。先从组成‘钢铁侠’的部件开始生产吧。”
既然是这样,那就从部件开始生产吧。
这里是“玩具厂”提供的“钢铁侠”右臂的“图纸”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1      public  class  RightHandComponent
2     {
3          public  RightHandComponent()
4         {
5              this .strName =  "毅代先锋号一代右部件" ;
6
7         }
8          public  RightHandComponent( string  strname)
9         {
10              this .strName = strname;
11         }
12          private  string  strName =  string .Empty;
13          public  string  Name
14         {
15              get  return  strName; }
16              set  { strName = value; }
17         }
18     }

还有一个左臂部件的“图纸”:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
1      public  class  LeftHandComponent
2     {
3          public  LeftHandComponent()
4         {
5              this .strName =  "毅代先锋号一代左部件" ;
6         }
7          private  string  strName =  string .Empty;
8          public  string  Name
9         {
10              get  return  strName; }
11              set  { strName = value; }
12         }
13     }

还有若干“图纸”…… 不在这篇一一列举了,在后面文章中会全面的讲解到。

开始生产

1
2
RightHandComponent rightcomponent =  new  RightHandComponent();
LeftHandComponent leftcomponent =  new  LeftHandComponent();

若干的部件 
被我一个个的按照图纸给制造了出来。
这样就可以拿rightcomponent、leftcomponent……等等的一些制造好的部件组装了。
我也可以给“玩具厂”打电话了,可以交货收钱。可是电话打完情况又变了,
中间的对话就不说了,“玩具厂”的意思就是这样的。比如说“运输途中”出现“损坏”,他们希望用一个很快捷便利的方式能得到部件。

简单工厂

嗯,我想了一下,不过对于我Jin叫兽来说都是小事,待我造出来一台部件生产器来。他们拿着机器自己回家生产不就ok了。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public  class  IronManComponentFactory
{
public  static  object  CreateComponent( string  comname)
{
switch  (comname)
{
case  "RightCom" :
return  new   RightHandComponent();
case  "LeftCom" :
return  new   LeftHandComponent();
等等……
}
return  null ;
}
}

这样生产的“机器”就好了,我得自己试用一下,看看效果怎么样。

1
2
1 RightHandComponent rightcomponent = IronManComponentFactory.CreateComponent( "RightCom" as  RightHandComponent;
2 LeftHandComponent leftcomponent = IronManComponentFactory.CreateComponent( "LeftCom" as  LeftHandComponent;
       这样反而多此一举了,第一步,向机器输入了命令以便自己获得想要的部件,第二步,在生产出来后我还得把“图纸”拿过来比对一下。 在我一筹莫展的时候,“玩具厂”给我发了个邮件,给我发了一份“部件规范说明书”,要求我的机器生产出的部件是达到说明书标准的。

那我们就来看一下这个所谓的“部件规范说明书”


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1     public  abstract  class  Component
2    {
3          private  string  strName =  string .Empty;
4          /// <summary>
5          /// 名称
6          /// </summary>
7          public  string  Name
8         {
9              get  return  strName; }
10              set  { strName = value; }
11         }
12          /// <summary>
13          /// 自我描述
14          /// </summary>
15          public  abstract  void  Self_Described();
16     }

看完这个“部件规范说明书”,我已经无力吐槽,没办法了,只有重新设计部件了,“图纸”要重新绘制,因为要按照那该死的“规范说明书”。
再看一下各个部件的“图纸”


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1      public  class  RightHandComponent:Component
2     {
3          public  RightHandComponent()
4         {
5             base .Name =  "毅代先锋号一代右部件" ;
6              //fWeight=材质输出
7         }
8          public  RightHandComponent( string  strname)
9         {
10              base .Name = strname;
11         }
12          public  override  void  Self_Described()
13         {
14             Console.WriteLine( base .Name);
15         }
16     }
17      public  class  LeftHandComponent:Component
18     {
19          public  LeftHandComponent()
20         {
21              base .Name =  "毅代先锋号一代左部件" ;
22         }
23          public  LeftHandComponent( string  strname)
24         {
25              base .Name = strname;
26         }
27          public  override  void  Self_Described()
28         {
29             Console.WriteLine( base .Name);
30         }
31     }

等等一些部件……

这下我再把原来的搭好的“生产机器”拆了,内部修改一下,来看一下修改后的“机器”


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1      public  class  IronManComponentFactory
2     {
3          public  static  Component CreateComponent( string  comname)
4         {
5              switch  (comname)
6             {
7                  case  "RightCom" :
8                      return  new  RightHandComponent();
9                  case  "LeftCom" :
10                      return  new  LeftHandComponent();
11
12             }
13              return  null ;
14         }
15     }

自己来测试一下:

1
2
3
4
1 Component rightcomponent = IronManComponentFactory.CreateComponent( "RightCom" );
2 Component leftcomponent = IronManComponentFactory.CreateComponent( "LeftCom" );
3 rightcomponent.Self_Described();
4 leftcomponent.Self_Described();

于是,我很放心的就交给了“玩具厂”使用了,还得了个好评。

工厂方法

好景不长,“玩具厂”再次来电,提出一个要求,想让我的“生产机器”里面还可以生产更多的符合“部件规范说明书”的部件。

这样说来是要改装“生产机器”了。 可以说“玩具厂”是故意的,绝对是故意的。这下整蒙圈了,亏血本了,“生产机器”又要拆了…… 直接来看“生产机器”的图纸

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public  abstract  class  IronManComponentFactory
2     {
3          protected  string  factoryName =  string .Empty;
4          protected  void  InitDataMessage()
5         {
6             Console.WriteLine( "生产机器:"  + factoryName +  ".准备就绪" );
7         }
8          public  abstract  Component CreateComponent();
9     }
10  public  class  RightComFactory:IronManComponentFactory
11     {
12
13          public  override  Component CreateComponent()
14         {
15              base .factoryName =  "右臂部件生产器" ;
16             InitDataMessage();
17              return  new  RightHandComponent();
18         }
19     }
20  public  class  LeftComFactory:IronManComponentFactory
21     {
22
23          public  override  Component CreateComponent()
24         {
25              base .factoryName =  "左臂部件生产器" ;
26             InitDataMessage();
27              return  new  LeftHandComponent();
28         }
29     }
30  public  class  PottingFactrory
31     {
32          /// <summary>
33          /// 取件口
34          /// </summary>
35          /// <param name="comFactory"></param>
36          /// <returns></returns>
37          public  static  Component ComExit(IronManComponentFactory comFactory)
38         {
39              if  (comFactory !=  null )
40             {
41                  return  comFactory.CreateComponent();
42             }
43              return  null ;
44         }
45     }

302100327206735.png

我们通过“取件口”取件


1
2
1 Component component = PottingFactrory.ComExit( new  RightComFactory());
2 component.Self_Described();

302102346586955.png

我们只要通过更换“生产插件”,从“取件口”获得不同的部件。 或者更改需求,又要生产符合“规范说明书”的另一些产品的时候,可以自定义来实现“生产插件”,插入“生产机器”即可。

这样可以送给“玩具厂”使用了。这次得到了很好的一个评价,我也可以休息一下了。

这里的工厂方法是开闭原则(OCP)的实现,很优雅的显示出了设计原则和设计模式的美。

抽象工厂

“对,没错。‘玩具厂’又来了……。”
这次“玩具厂”是把Iron部件升级了,二代部件出来了,是在一代的基础上做了一些个性化的设计。来看新增部件的“图纸”


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1      public  class  RightHandComponent2 : Component
2     {
3          public  RightHandComponent2() :  this ( "毅代先锋号二代右部件" ) { }
4          public  RightHandComponent2( string  strname)
5         {
6              base .Name = strname;
7         }
8          public  override  void  Self_Described()
9         {
10             Console.WriteLine( "自描述:我是->"  base .Name);
11         }
12     }
13
14      public  class  LeftHandComponent2 : Component
15     {
16          public  LeftHandComponent2() :  this ( "毅代先锋号一代左部件" ) { }
17          public  LeftHandComponent2( string  strname)
18         {
19              base .Name = strname;
20         }
21          public  override  void  Self_Described()
22         {
23             Console.WriteLine( "自描述:我是->"  base .Name);
24         }
25     }

按照“规范说明书”,添加了两张“图纸”,它们分别是二代的左右手部件。

部件的整体结构没怎么变,但是“生产机器”的“规范说明”就要更改了,以为在上面说到的“生产插件”也要重新更改。

先来看一下“生产机器”的“规范说明”:


1
2
3
4
5
6
7
8
9
10
11
12
1     public  abstract  class  IronManComponentFactory
2    {
3         protected  string  factoryName =  string .Empty;
4         protected  void  InitDataMessage()
5        {
6            Console.WriteLine( "生产机器:"  + factoryName +  ".准备就绪" );
7        }
8         public  abstract  Component CreateComponent();
9         public  abstract  Component CreateComponent2();
10
11
12    }

当然喽,“规范说明”都改了,那上面说过的两个生产插件也得改了:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public  class  RightComFactory : IronManComponentFactory                    //右部件生产插件
2     {
3
4          public  override  Component CreateComponent()
5         {
6              base .factoryName =  "新右臂部件生产器" ;
7             InitDataMessage();
8              return  new  RightHandComponent();
9         }
10
11          public  override  Component CreateComponent2()
12         {
13              base .factoryName =  "新右臂部件生产器" ;
14             InitDataMessage();
15              return  new  RightHandComponent2();
16         }
17     }
18
19  public  class  LeftComFactory : IronManComponentFactory               //左部件生产插件
20     {
21
22          public  override  Component CreateComponent()
23         {
24              base .factoryName =  "新左臂部件生产器" ;
25             InitDataMessage();
26              return  new  LeftHandComponent();
27         }
28
29          public  override  Component CreateComponent2()
30         {
31              base .factoryName =  "新左臂部件生产器" ;
32             InitDataMessage();
33              return  new  LeftHandComponent2();
34         }
35     }

所要做的修改都是连带关系,包装”生产机器“的”取件口“也要改:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public  class  PottingFactory
2    {
3         private  IronManComponentFactory comFactory =  null ;
4
5         public  IronManComponentFactory ComFactory
6        {
7             get  return  comFactory; }
8             set  { comFactory = value; }
9        }
10         public  PottingFactory(IronManComponentFactory comFactory)
11        {
12             this .comFactory = comFactory;
13        }
14         /// <summary>
15         /// 取件口
16         /// </summary>
17         /// <param name="comFactory"></param>
18         /// <returns></returns>
19         //public static Component ComExit(IronManComponentFactory comFactory)
20         //{
21         //    if (comFactory != null)
22         //    {
23         //        return comFactory.CreateComponent();
24         //    }
25         //    return null;
26         //}
27    }

到这里就差不多结束了。在工厂方法模式上 做了稍稍的(几乎全改了)改动。

当然自己要先来测试一下喽:


1
2
3
4
5
1 PottingFactory pottingfact =  new  PottingFactory( new  RightComFactory());
2 Component component= pottingfact.ComFactory.CreateComponent();
3 component.Self_Described();
4 component = pottingfact.ComFactory.CreateComponent2();
5 component.Self_Described();
我们来看一下结果:

302135533616570.png

End IronMan之旅才刚刚开始

 





     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1409120,如需转载请自行联系原作者




相关文章
|
12月前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
262 40
|
10月前
|
设计模式 Java
课时89:工厂设计模式
课时89介绍工厂设计模式(Factory),涵盖接口的定义与使用、程序结构设计及工厂设计的核心概念。通过实例代码展示如何利用接口实现子类的向上转型,并通过工厂类解耦主类与子类的关系,从而实现更灵活和可扩展的设计。工厂模式使客户端无需关心具体子类的创建过程,仅需通过工厂类获取对象实例,简化了系统的维护和扩展。
141 1
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
207 2
|
设计模式 安全 Java
C# 一分钟浅谈:设计模式之单例模式
【10月更文挑战第9天】单例模式是软件开发中最常用的设计模式之一,旨在确保一个类只有一个实例,并提供一个全局访问点。本文介绍了单例模式的基本概念、实现方式(包括饿汉式、懒汉式和使用 `Lazy&lt;T&gt;` 的方法)、常见问题(如多线程和序列化问题)及其解决方案,并通过代码示例详细说明了这些内容。希望本文能帮助你在实际开发中更好地应用单例模式,提高代码质量和可维护性。
562 1
|
设计模式 算法 C#
C#设计模式之策略模式
C#设计模式之策略模式
225 19
|
设计模式 C# 开发者
C#设计模式入门实战教程
C#设计模式入门实战教程
166 3
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
330 1
|
设计模式 XML 数据格式
python之工厂设计模式
python之工厂设计模式
python之工厂设计模式
|
设计模式 安全 程序员
C#设计模式之单例模式
C#设计模式之单例模式
172 3
|
设计模式 Java 编译器
设计模式——创建型模式(工厂,简单工厂,单例,建造者,原型)
设计模式——创建型模式(工厂,简单工厂,单例,建造者,原型)