更新1:使用as转换数据类型。

在上篇文章 我的实用设计模式 - Simple Factory,Factory Method和Abstract Factory 讲述了Simple Factory,Factory Method和Abstract Factory的关系以及演变过程。在这篇文章中,引入Reflection来实现Simple Factory,增强系统的可扩展性。

下面是Reflection在msdn的定义
Reflection provides objects (of type Type) that describe assemblies, modules and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.

我的理解是Reflection在运行时提供从assemblies(.NET平台下编译生成的DLL或者EXE文件)取出Metadata信息的功能,然后可以对Metadata的信息进行读取,修改,以及动态的根据这些Metadata生成对象。

由于.NET平台提供Reflection,意味着.NET开发的assemblies很容易就可以进行disassemble(反编译),同时也可以通过Reflection调用一下非public的Methods,但是这些不是这篇文章讨论的范围。

现在先看回上篇文章中Simple Factory的实现。

public enum GameDiskType
{
    Racing,
    Shooting,
    Fighting
}

public sealed class PS3DiskFactory
{
    public static AbstractGameDisk CreateGameDisk(GameDiskType type)
    {
        switch (type)
        {
            case GameDiskType.Racing:
                return new PS3RacingGameDisk();
            case GameDiskType.Shooting:
                return new PS3ShootingGameDisk();
            case GameDiskType.Fighting:
                return new PS3FightingGameDisk();
            default:
                return null;
        }
    }
}

为了方便演示Reflection,我把GameDiskType的定义修改了一下,区分大小写。从原先没有使用模式,直接在Client new对象的方式到使用Simple Factory,实现了对对象实例化过程的封装,所有的对象实例化变化被封装到PS3DiskFactory的工厂类里面了。这一步符合设计原则“封装变化”。可是有人会问,在PS3DiskFactory里面,如果新增GameDisk还是需要修改条件从句(switch...case),和原先的设计没有太大的改变,从Refactoring的角度看,代码还是有臭味道。 Well,Well,Well,你的鼻子真灵呀。这里涉及到设计上的边界(Boundary)问题。从Client类看,PS3DiskFactory确实把对象初始化的需求封装了,变化不会在Client类里面发生。从整个系统来看,对象初始化的变化,还是需要修改源代码(例如修改PS3DiskFactory),那怎么解决这个问题了,在.NET里面提供了Reflection可以解决这个问题。

public sealed class PS3DiskFactory
{
    public AbstractGameDisk CreateGameDisk(GameDiskType type)
    {
        // Get fully qualified factory name
        string name = this.GetType().Namespace + ".PS3" + type.ToString() + "GameDisk";

// Dynamic factory creation
        return System.Activator.CreateInstance(Type.GetType(name)) as AbstractGameDisk;
    }
}

在CreateGameDisk里面,先组成需要实例化的类的全名称(fully qualified name),然后使用System.Activator.CreateInstance来生成。上面是PS3DiskFactory的代码,用于实例化PS3的GameDisk,可以看到生成全名称的时候hard code了”PS3“。如果把设备名字作为参数传递到工厂中,那么一个工厂就可以同时生成PS3和Wii的GameDisk了。

public enum GameDevice
{
    PS3,
    Wii
}

public sealed class DiskFactory
{
    public AbstractGameDisk CreateGameDisk(GameDevice device, GameDiskType type)
    {
        // Get fully qualified factory name
        string name = this.GetType().Namespace + "." + device.ToString() + type.ToString() + "GameDisk";

// Dynamic factory creation
        return System.Activator.CreateInstance(Type.GetType(name)) as AbstractGameDisk;
    }
}

在上述代码中,要实例化的对象的namespace是和当前工厂类是同一个namespace,同样要实例化的类和工厂类在同一个Assembly里面。当然他们可以分布于不同的assemblies。拿上篇文章的Asbtract Factory的工厂类作为例子,如果不同的游戏机类型,其Concrete Factories和Concrete Products分别独立存在于一个namespace和assembly,例如

namespace PS3
{
    public class PS3Console : AbstractGameConsole
    {
    }

public class PS3Joystick : AbstractJoystick
    {
    }
    
    public class PS3Player : AbstractPlayer
    {
        public override AbstractGameDisk CreateGameDisk(GameDiskType type)
        {
            return new PS3RacingGameDisk();
        }

public override AbstractGameConsole CreateGameConsole()
        {
            return new PS3Console();
        }
        public override AbstractJoystick CreateJoystick()
        {
            return new PS3Joystick();
        }
    }
}

名字空间(namespace)为PS3的程序编译到PS3Factory.dll中,而Wii的实现在WiiFactory.dll中,以下是原有没有使用Reflection的实现。

public enum GameDevice
{
    PS3,
    Wii
}

public class Player
{
    private AbstractPlayer playerFactory;

public Player(GameDevice device)
    {
        switch (device)
        {
            case GameDevice.PS3:
                playerFactory = new PS3Player();
                break;
            case GameDevice.Wii:
                playerFactory = new WiiPlayer();
                break;
        }
    }
}

使用Reflection后,可以把switch去掉,代码如下:

public class Player
{
    private AbstractPlayer playerFactory;
    public Player(GameDevice device)
    {
        //Load Assembly
        Assembly asm = Assembly.LoadFrom(device.ToString() + "Factory.dll");

// Get fully qualified factory name
        string name = device.ToString() + "." + device.ToString() + "Player";
        // Dynamic factory creation
        playerFactory = asm.CreateInstance(name) as AbstractPlayer;
    }
}

GameDevice可以来自于配置文件。使用Reflection后,系统动态plug-in新的模块,例如需要增加Xbox模块,把Xbox的Concrete Factories和Concrete Products实现封装到Xbox的namespace,同时编译到XboxFactory.dll,修改GameDevice的配置文件就可以了。

参考文献:

Reflection (C# Programming Guide)

本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/04/30/1447024.html,如需转载请自行联系原作者

我的实用设计模式 - Simple Factory和Reflection相关推荐

  1. 我的实用设计模式之Simple Factory,Factory Method和Abstract Factory

    更新1:更新Factory Method部分,说明文中使用"参数化工厂方法"的实现,同时加入经典Factory Method的实现进行比较. 更新2:更新Abstract Fact ...

  2. Net设计模式之简单工厂模式(Simple Factory Pattern)

    一.简单工厂模式简介(Bref Introduction)        简单工厂模式(Simple Factory Pattern)的优点是,工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实 ...

  3. Java设计模式(1)——创建型模式之简单工厂模式(Simple Factory)

    设计模式系列参考: http://www.cnblogs.com/Coda/p/4279688.html 一.概述 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高 ...

  4. 设计模式的征途—2.简单工厂(Simple Factory)模式

    工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的"小弟",我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式, ...

  5. 设计模式(1):简单工厂模式(Simple Factory Pattern)

    1. 从一个简单的例子开始 在众多的设计原则中,有一条原则是这么说的:要针对接口编程,不要针对实现编程. 针对接口编程的话,可以使用不同的实现类来创建这个对象.比如需要一个List: List< ...

  6. 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式(转载)

    源地址:http://doc.chinaunix.net/python/200703/202210.shtml 本文详细介绍Python 设计模式系列之二: 创建型 Simple Factory 模式 ...

  7. 设计模式(4)—— 简单工厂模式(Simple Factory,创建型)

    1.概述 使用设计模式可以提高代码的可复用性.可扩充性和可维护性.简单工厂模式(Simple Factory Pattern)属于创建型模式.简单工厂模式,由一个工厂对象决定创建出哪一种产品类的实例, ...

  8. C#设计模式(4)-Simple Factory Pattern

    工厂模式专门负责将大量有共同接口的类实例化.工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类.工厂模式有以下几种形态: 简单工厂(Simple Factory)模式 工厂方法(F ...

  9. Java设计模式之简单工厂模式(Simple Factory)

    [Java与模式]简单工厂模式(Simple Factory---吴义) 首先说明,Java与模式一系列的文章均是参考阎宏博士的<Java与模式>一书,加上自身的一些体会的探索,产生如下文 ...

最新文章

  1. 声网sdk android接入,Android 集成声网Agora 音视频实时通话(三)
  2. 怎样给RCP程序添加依赖的JAR包
  3. [YTU]_2018 ( 约瑟夫问题)
  4. 微服务网关Zuul迁移到Spring Cloud Gateway
  5. spring启动过程之源码跟踪(上)--spring Debug
  6. 2017年11月04日普及组 Biotech
  7. helloworld讲解cocos2d-x的编程思路与要点
  8. Redis的七种武器及其适合的应用场景
  9. php kibana查询,搜索您的数据 | Kibana 用户手册 | Elastic
  10. 我的Android进阶之旅------gt;Android Studio 快捷键整理分享
  11. 视觉中国、IC photo被责令暂停服务全面整改
  12. 解决DDOS攻击生产案例
  13. 微信分享wx.config配置时遇到invalid signature错误的解决办法
  14. word打印高清图片
  15. 《德鲁克管理思想精要》读书笔记11 - 管理你的下半生
  16. poi word设置页眉图片,控制首页不同
  17. 大牛的学习笔记:步进电机驱动在3D打印应用
  18. FullCalendar-vue demo例子
  19. 指定IDEA的字符编码
  20. Windows 使用技巧

热门文章

  1. 程序员的数学3 线性代数_在编程大佬眼中,线性代数到底是什么样的?
  2. 离散数学专业术语(continuous updating)
  3. ‘pip 安装第三方库速度太慢’的解决办法
  4. 谈谈Mux与门电路的相互替换(包含实例分析)
  5. Habitica 4.85.5 发布,习惯游戏养成应用
  6. JVM运行时数据区域
  7. 今日SGU 5.25
  8. 0元力压0.1元,中国电信中标连云港政务云项目
  9. js 阻断网页选中和右键
  10. 从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读