码迷,mamicode.com
首页 > 其他好文 > 详细

C#之工厂模式

时间:2014-05-01 03:06:39      阅读:379      评论:0      收藏:0      [点我收藏+]

标签:des   com   http   blog   style   class   div   img   code   c   java   

IronMan之工厂

前言

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

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

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

 

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

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

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

问题的发现

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

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

mamicode.com,码迷
 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     }
mamicode.com,码迷

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

 

mamicode.com,码迷
 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     }
mamicode.com,码迷

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

开始生产

mamicode.com,码迷
RightHandComponent rightcomponent = new RightHandComponent();
LeftHandComponent leftcomponent = new LeftHandComponent();
mamicode.com,码迷

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

简单工厂

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

mamicode.com,码迷
    public class IronManComponentFactory
    {

        public static object CreateComponent(string comname)
        {
            switch (comname)
            {
                case "RightCom":
                    return new  RightHandComponent();
                case "LeftCom":
                    return new  LeftHandComponent();

                等等……
            }
            return null;
        }
    }
mamicode.com,码迷

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

mamicode.com,码迷
1 RightHandComponent rightcomponent = IronManComponentFactory.CreateComponent("RightCom") as RightHandComponent;
2 LeftHandComponent leftcomponent = IronManComponentFactory.CreateComponent("LeftCom") as LeftHandComponent;
mamicode.com,码迷

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

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

mamicode.com,码迷
 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     }
mamicode.com,码迷

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

mamicode.com,码迷
 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     }
mamicode.com,码迷

等等一些部件……

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

mamicode.com,码迷
 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     }
mamicode.com,码迷

自己来测试一下:

mamicode.com,码迷
1 Component rightcomponent = IronManComponentFactory.CreateComponent("RightCom");
2 Component leftcomponent = IronManComponentFactory.CreateComponent("LeftCom");
3 rightcomponent.Self_Described();
4 leftcomponent.Self_Described();
mamicode.com,码迷

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

工厂方法

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

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

mamicode.com,码迷
mamicode.com,码迷
 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     }
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     }
View Code
mamicode.com,码迷

mamicode.com,码迷

我们通过“取件口”取件

mamicode.com,码迷
1 Component component = PottingFactrory.ComExit(new RightComFactory());
2 component.Self_Described();
mamicode.com,码迷

mamicode.com,码迷

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

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

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

抽象工厂

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

mamicode.com,码迷
 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     }
mamicode.com,码迷

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

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

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

mamicode.com,码迷
 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    }
mamicode.com,码迷

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

mamicode.com,码迷
 1 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     }
mamicode.com,码迷

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

mamicode.com,码迷
 1 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    }
mamicode.com,码迷

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

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

mamicode.com,码迷
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();
mamicode.com,码迷

我们来看一下结果:

mamicode.com,码迷

 End   IronMan之旅才刚刚开始

 

         

C#之工厂模式,码迷,mamicode.com

C#之工厂模式

标签:des   com   http   blog   style   class   div   img   code   c   java   

原文地址:http://www.cnblogs.com/jin-yuan/p/3702263.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!