C# Design Patterns (1) - Factory Method

Simple Factory Pattern (简单工厂模式)

特性:

把类的实例化工作,集中到一个「工厂类」去处理,亦即将 new instance 的工作,都交给一个「工厂」去处理,而不要分散写在各个类中。客户端程序,与创建实例 (对象) 的工作必须隔离,亦即「解耦」,客户端程序只要专注于自己的业务逻辑。适用于客户端程序在开发过程中,尚无法预知要创建的具体类型。产品具体的实现能和客户端隔离,便于事后抽换。

Simple Factory Pattern (简单工厂模式)、Factory Method Pattern (工厂方法模式),在实作的代码中,有时很难明确去界定此二者。Simple Factory 的特性,如前所述,在于将创建实例 (new instance) 的工作,集中由特定的一个「工厂类」来处理,避免写在各个类中,以方便日后添加新功能,和修改既有的功能。

如下「进口水果」的代码,为 O'Reilly 的「C# 3.0 Design Patterns」这本书籍 [1] 第五章的 Factory Method 示例。乍看之下,我觉得它比较像 Simple Factory Pattern,因其仍将创建实例,和部分逻辑判断的工作,都集中在一个 工厂类 (Creator1 类) 去处理,导致日后要添加新功能 (多引进一个国家的水果),或要修改判断「进口月份」的逻辑时,仍要修改 server-side 的这个「工厂类」,而无法只修改 client-side 的 Page_Load 方法,违背了「开放-封闭」原则。

但这个示例,要实例化哪个类型,是由「工厂类」以及客户端 (水果店主人) 的 Page_Load 方法,共同决定的。透过 IProduct 接口,看似隔离了客户端程序、具体 Product 的依赖关系,但客户端程序仍有创建对象的决定权,因此其与创建实例 (对象) 的工作并未真正隔离。

SimpleFactory.
aspx.cs

using System;

//这个示例事实上算是一个 Factory Method Pattern

public partial class SimpleFactory : System.Web.UI.Page

{

    //客户端调用(Client-Side)。这个示例的客户端,如
同一间水果店的店主人。

    protected void Page_Load(object sender, EventArgs e)

    {

        Creator1 c = new Creator1();    //工厂类

        IProduct product;

//由客户端决定要具体实例化哪些类型。

        //但此示例的特点,为客户端不需要知道产品类型。

        for (int i = 1; i <= 12; i++)

        {

            //客户端不需要知道产品类型。把创建哪种具体产品的决定,委托给了工厂方法

            product = c.factoryMethod(i);

            Response.Write("水果进口, " + i + "月: " + product.shipFrom() + "

");

        }

    }

//这个示例,要实例化哪个类型,是由「工厂类」以及 Client-Side 的 Page_Load() 方法,共同决定的。

    //透过 IProduct 接口,看似隔离了客户端程序、具体 Product 的依赖关系,

    //但客户端程序仍有创建对象的决定权,因此其与创建实体 (对象) 的工作并未真正隔离。

    

    //即使日后修改了某个子类 shipFrom() 里的实作方式,对客户端不会有影响,

    //客户端只要知道如何操作 shipFrom() 去进口水果即可。

}

//所有的产品,必须实现这个接口。如此一来,先建立一种「契约」,

//以后要增添、修改产品时,就可由这个接口(或抽象类)来操作。

interface IProduct

{

    //隐藏实现细节。

    //事前不知道要创建哪种类的实体(产品),延至 Creator1 类或「客户端」中实现。

    string shipFrom();

}

//单一职责原则,每一个类都只负责一件具体的事情。

// 台湾的水果供货商。

class ProductA : IProduct

{

    public string shipFrom()

    {

        return " from 台湾";

    }

}

//单一职责原则,每一个类都只负责一件具体的事情。

// 美国的水果供货商。

class ProductB : IProduct

{

    public string shipFrom()

    {

        return "from 美国";

    }

}

//单一职责原则,每一个类都只负责一件具体的事情

class DefaultProduct : IProduct

{

    public string shipFrom()

    {

        return "不进口";

    }

}

//工厂类 (水果采购人员),负责创建实体(采购水果)。只有这个类,知道如何创建这些产品的逻辑

class Creator1

{

    //日后若引进新产品 (多引进一个国家的水果)、修改旧产品,可集中在这里抽换;

    //但缺点亦如是,亦即仍需修改这里的 Server-Side 代码,必须修改此一工厂类。

//此处做法,偏向「简单工厂模式」的实体创建。

    public IProduct factoryMethod(int month)

    {

        if (month >= 4 && month <= 11)

            return new ProductA();

        else

            if (month == 1 || month == 2 || month == 12)

                return new ProductB();

            else

                return new DefaultProduct();

    }

}

//另一个工厂类

//class Creator2

//{

//    public IProduct factoryMethod(int month, int day)

//    {

//        不同的水果进口方式

//    }

//}

/* 

执行结果:

水果进口, 1月: from 美国

水果进口, 2月: from 美国

水果进口, 3月: 不进口

水果进口, 4月: from 台湾

水果进口, 5月: from 台湾

水果进口, 6月: from 台湾

水果进口, 7月: from 台湾

水果进口, 8月: from 台湾

水果进口, 9月: from 台湾

水果进口, 10月: from 台湾

水果进口, 11月: from 台湾

水果进口, 12月: from 美国

*/

//

图 1 Sybase PowerDesigner 绘制的「进口水果」示例的 Class Diagram

--------------------------------------------------------

Factory Method Pattern (工厂方法模式)

特性:

由子类来决定要具体实例化哪种类型。这些子类实现了某个共通的接口,或继承自某个共用的抽象类。让一个类的实例化,延迟到其子类。由客户端程序,来决定要创建哪些工厂类型。

上述特性的第一点,所提到的子类,如同下方示例里的「博派Factory」类、「狂派Factory」类。

上述特性的第三点,Factory Method 和 Simple Factory 刚好相反。Factory Method 把 Simple Factory 中「工厂类」的逻辑判断,移到客户端来进行。日后若想添加、修改功能,原本 Simple Factory 是要修改「工厂类」的,但 Factory Method 变成要修改客户端程序,但也改善了 Simple Factory 的缺点,亦即不用再冒险修改原本已可正常工作的 server-side「工厂类」,而只要改 client-side 的 Page_Load 方法,符合了「开放-封闭」原则。

Factory Method 的实现方式有很多种,但原则为,先用一个抽象类或接口,当作定义 (如下方示例的 IFactory),并留下抽象方法而不实作 (如下方示例的 createTransformer 方法)。要延迟到子类,由子类来决定要实例化哪种类型 (如下方示例的「博派Factory」和「狂派Factory」这两个子类)。

FactoryMethod.aspx.cs

using System;

public partial class FactoryMethod : System.Web.UI.Page

{

    //客户端调用(Client-Side)。

    protected void Page_Load(object sender, EventArgs e)

    {

        //客户端程序调用的时候,只要改右侧创建实体的类型即可

        IFactory factory1 = new 博派Factory();

        变形金刚 擎天柱 = factory1.createTransformer();

        擎天柱.transformCar();

//把职责委托给平行层次中的子类

        IFactory factory2 = new 狂派Factory();

        变形金刚 威震天 = factory2.createTransformer();

        威震天.transformAirplane();

    }

}

//IProduct

class 变形金刚

{

    public virtual void transformCar()

    {

        Console.WriteLine("变汽车");

    }

public virtual void transformAirplane()

    {

        Console.WriteLine("变飞机");

    }

public virtual void transformAnimal()

    {

        Console.WriteLine("变动物");

    }

}

//IProduct 的子类

class 博派 : 变形金刚

{ }

//IProduct 的子类

class 狂派 : 变形金刚

{ }

//变形金刚工厂 (亦可用抽象类)

interface IFactory

{

    //隐藏实现细节。

    //事前不知道要创建哪种变形金刚,延至「客户端」中实现。

    变形金刚 createTransformer();

}

//博派的工厂 (由此种子类来决定具体实例化哪种类型)

class 博派Factory : IFactory

{

    public 变形金刚 createTransformer()

    {

        return new 博派();

    }

}

//狂派的工厂 (由此种子类来决定具体实例化哪种类型)

class 狂派Factory : IFactory

{

    public 变形金刚 createTransformer()

    {

        return new 狂派();

    }

}

//以后引进新产品 (堕落金刚) 时,我们不需要冒险修改既有的「工厂类」,而只要添加
新的产品类、新的工厂类,

//最后由 IFactory 的子类,以及客户端程序 (Page_Load 方法),来决定要创建哪些具体类型;

//整个架构变成只有「扩展」的变化,而不再有「修改」的变化。

//若要修改旧功能,如狂派类,要加入组合成「大力神」的功能时,也只需要修改既有的「狂派」类。

图 2 Sybase PowerDesigner 绘制的「变形金刚 - 工厂方法模式」Class Diagram

以后引进新产品 (堕落金刚) 时,我们不需要冒险修改既有的「工厂类」,而只要添加新的「产品类」、新的「工厂类」,最后由 IFactory 的子类,以及客户端程序 (Page_Load 方法),来决定要创建哪些具体类型;整个架构变成只有「扩展」的变化,而不再有「修改」的变化。此外,若要修改旧功能,如:「狂派」类,要加入组合成「大力神」的功能时,也只需要修改既有的「狂派」类即可。

Factory Method Pattern 并无固定的实现方式,上述两个示例,仅为其中一种实现方式,若参考一些 Java 的论坛、书籍、文件,还能找到更多的变化应用 [7], [8]。

时间: 2024-08-02 03:42:47

C# Design Patterns (1) - Factory Method的相关文章

艾伟_转载:C# Design Patterns (1) - Factory Method

Simple Factory Pattern (简单工厂模式) 特性: 把类的实例化工作,集中到一个「工厂类」去处理,亦即将 new instance 的工作,都交给一个「工厂」去处理,而不要分散写在各个类中. 客户端程序,与创建实例 (对象) 的工作必须隔离,亦即「解耦」,客户端程序只要专注于自己的业务逻辑.适用于客户端程序在开发过程中,尚无法预知要创建的具体类型. 产品具体的实现能和客户端隔离,便于事后抽换. Simple Factory Pattern (简单工厂模式).Factory M

艾伟:C# Design Patterns (1) - Factory Method

Simple Factory Pattern (简单工厂模式) 特性: 把类的实例化工作,集中到一个「工厂类」去处理,亦即将 new instance 的工作,都交给一个「工厂」去处理,而不要分散写在各个类中. 客户端程序,与创建实例 (对象) 的工作必须隔离,亦即「解耦」,客户端程序只要专注于自己的业务逻辑.适用于客户端程序在开发过程中,尚无法预知要创建的具体类型. 产品具体的实现能和客户端隔离,便于事后抽换. Simple Factory Pattern (简单工厂模式).Factory M

艾伟:C# Design Patterns (2) - Strategy

Strategy Pattern (策略模式) 所谓 Strategy Pattern 的精神,就是将策略 (算法) 封装为一个对象,易于相互替换,如同 USB 设备一样可即插即用:而不是将策略.具体的算法和行为,硬编码在某个类或客户程序中,导至事后的修改和扩展不易. 若有多种「策略」,就将这些个策略,和这些策略的算法.行为,封装在各个类中,并让这些类,去继承某个公用的抽象类或接口.接着在客户程序中,就可动态引用,且易于更换这些不同的「策略」,不会因为日后添加.修改了某一个「策略」,就得重新修改

艾伟_转载:C# Design Patterns (2) - Strategy

Strategy Pattern (策略模式) 所谓 Strategy Pattern 的精神,就是将策略 (算法) 封装为一个对象,易于相互替换,如同 USB 设备一样可即插即用:而不是将策略.具体的算法和行为,硬编码在某个类或客户程序中,导至事后的修改和扩展不易. 若有多种「策略」,就将这些个策略,和这些策略的算法.行为,封装在各个类中,并让这些类,去继承某个公用的抽象类或接口.接着在客户程序中,就可动态引用,且易于更换这些不同的「策略」,不会因为日后添加.修改了某一个「策略」,就得重新修改

Design Pattern: Factory Method 模式

考虑一个状况,您所经营的工厂正在生产一个新的电视机产品,现在有一个问题发生了,您的电视机产品所有的组件都可以自行生产,像是操作面版.电源.摇控装置等等等,但荧幕却必须依赖另一个厂商或子厂商供应,这时您怎么办? 您不能将生产进度停下了,相反的您必须确定一些事情,您知道有关于荧幕控制的所有介面,您可以将这些对介面的操作沟通先实现,等到荧幕到了,直接将荧幕与您的半成品组合起来,一个完整的成品即可出厂. Factory Method模式在一个抽象类中留下某个创建元件的抽象方法没有实作,其它与元件操作相关

《Design Patterns》学习总结

在时间比较空余的时候,又找到一本一直想看的书,就是这本名为<Design Patterns>(Gang of Four)的著作.本书通过类似Window Doc的程序,来揭开设计模式学习序幕,通过分析设计程序时遇到的困难,引出可以解决问题的设计模式,从而引导你更全面的掌握设计模式.案例程序的设计引出8个设计模式,案例程序设计完成后就是单独的23个经典设计模式,可以单个查阅,单个阅读. Abstract Factory模式 这个模式似乎离我比较远,因为本人还从未开发过在此模式讲解过程中介绍到的设

Head First Design Patterns

    在更大的计划之前,先温习一下Design Pattern的功课.    看了<Head First Design Patterns>里讲Decorator的样章,发现JOLT大奖不是白拿的,叙事能力之强,表达之清晰,不是那些满腹经伦的老先生可以比的.而且整个Pattern的讲述过程循序渐进,真的可以保证--小白都能学会设计模式.    可惜就只有样章.Head First系列的电子书都不好找,只好还是翻出老先生们的书来看.    这次温习很快做完,其实GOF80%的模式,都是基于一个原

乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) 作者:webabcd 介绍 定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例 有SqlMessage和XmlMessage,用Factory Method来实例化它们. MessageModel using Syst

C# Design Patterns (4) - Proxy

本帖介绍 Proxy Pattern (代理模式). Proxy Pattern (代理模式) The Proxy Pattern provides a surrogate or placeholder for another object to control access to it...                                  - Design Patterns: Elements of Reusable Object-Oriented Software 在 Go