今天给大家带来的是:工厂模式。

  我们在代码中创建一个对象,我们会很自然的想到new。其实,除了new意外,我们还有很多的方式可以创建对象。不说复杂的模式,就说简单的语法,其实.NET框架中还有下面的方法。根据需要创建的对象的类型,动态创建对象。

  

Activator.CreateInstance

  通过前面我们已经讲过一条原则:

  针对接口编程,不针对实现编程。

  使用new创建对象很明显就是一个针对实现编程,new后面需要一个具体的类,不允许你new一个接口或者是抽象类。包括用Activator.CreateInstance都不能创建接口或者抽象类。

  那是不是就是说以后不能或者是不要再用new了,都用其他方式吗?

  也不是的,也要根据情况来分析,不是一概而论的,在后面会给出一些简单的标准,更多的要结合具体的设计定夺。

  很多时候我们会碰到下面的代码:

  

代码

     string userType = "";
                if (userType == "admin")
                {//创建管理员
                }
                else if (userType == "supervisor")
                {//创建超级管理员
                }
                else if (userType == "coommon")
                {
                    //创建普通用户
                }

  如果以后增加了用户的类型,不仅要创建用户类型实体,还需要打开创建用户的这段代码,后面加上一个if。。。else。。。。

  如果这段代码没有封装,就更麻烦了,散落在项目的各处,每个地方都要打开,ctrl+c,ctrl+v。开始了无尽的噩梦。

  对于后面的维护成了问题,而且违反了一条原则:

   

  OCP原则,对增加开放,对修改封闭。

  首先使用封装变化原则对这段代码做一些抽象,上面这段明显是变化较多的地方,其他的代码可能是现实创建的用户的姓名之类的。变成一个方法,然后将用户类型定义为enum类型,减少调用者由于输入错误导致程序错误。

  

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.DesignPattern.Head.First.Factory
{
    public enum UserType
    {
        Admin,
        Supervisor,
        Common
    }
    public abstract class User
    {
        public virtual UserType UserType
        {
            get;
            protected set;
        }
        public User(UserType userType)
        {
            UserType = userType;
        }
        public virtual string Username
        {
            get;
            set;
        }
        public virtual int Age
        {
            get;
            set;
        }
        public virtual void DisplayName()
        {
            Console.WriteLine("my name is {0}, i'm {1} years old.", Username, Age);
        }
    }
    public class AdminUser : User
    {
        public AdminUser()
            : base(UserType.Admin)
        { }
    }
    public class CommonUser : User
    {
        public CommonUser()
            : base(UserType.Common)
        { }
    }
    public class SupervisorUser : User
    {
        public SupervisorUser()
            : base(UserType.Supervisor)
        {
        }
    }
}

  

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.DesignPattern.Head.First.Factory
{
   public  class UserFactory
    {
       public static User CreateSingleUser(UserType userType)
       {
           User user = null;
           switch (userType)
           {
               case UserType.Admin :
                   user = new AdminUser(); 
                   break;
               case UserType.Common :
                   user = new CommonUser();
                   break;
               case  UserType.Supervisor :
                   user = new SupervisorUser();
                   break;
               default :
                   break;
           }
           return user;
       }
    }
}

  调用代码

Head.First.Factory.User user = Head.First.Factory.UserFactory.CreateSingleUser(Head.First.Factory.UserType.Admin);

  以后增加新的用户类型就不用在各处修改了,只要新建一个类型实体,然后打开工厂方法,修改一下就可以了。

  有没有更好的呢?

  能否只是增加一个用户类型实体类呢?

  答案是:能

  修改一下工厂方法,利用泛型和Activator

  

 public static T CreateSingleUser2<T>() where T:User
       {
           T user = null;
           user = Activator.CreateInstance<T>();
           return user;
       }

  调用者的代码修改为

  

 Head.First.Factory.User user1 = Head.First.Factory.UserFactory.CreateSingleUser2<Head.First.Factory.AdminUser>();

  有没有更好的呢?

  期待大家的参与讨论!!!!

  其实我这个还不算是真正意义上的工厂模式,顶多算是个简单的工厂,后面我会补充一些更好的例子。

  感谢大家耐心看完本篇博文。

  定义

  工厂模式:定义了一个创建对象的借口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到了子类。

  上面的描述中提到了“子类决定”的决定,希望不要错误理解,不是模式允许子类本身在运行的时候做决定,而是指在编写创建者类的时候,不需要知道实际创建的类是哪一个。调用者选择使用哪个类,自然就决定了实际创建的对象。

《深入浅出设计模式-中文版》读书笔记-工厂模式(五)相关推荐

  1. 《Head First 设计模式》读书笔记——工厂模式

    今天是第几天我也忘了,反正就是继续写.前几天的还需要完善,今天力求完整! 奠定基调的例子 作为一名披萨店店主,我们需要售卖不同种类的披萨,所以就需要设计很多披萨的类型,并且需要增加一下代码来确定顾客需 ...

  2. 《深入浅出DPDK》读书笔记(十五):DPDK应用篇(Open vSwitch(OVS)中的DPDK性能加速)

    Table of Contents Open vSwitch(OVS)中的DPDK性能加速 174.虚拟交换机简介 175.OVS简介 176.DPDK加速的OVS 177.OVS的数据通路 178. ...

  3. 《大话设计模式》读书笔记-建造者模式

    // 建造者类     class PersonDirector     {         private PersonBuilder pb; public PersonDirector(Perso ...

  4. 《Head First 设计模式》读书笔记——迭代器模式

    让客户遍历我们的数组.堆栈.列表或者散列表时,无法知道我们存储对象的方式,就靠今天的迭代器模式了. 案例 我们有两个餐饮店要合并经营,他们的菜品有共同的地方,所以我们这两个商店类需要一个共同的菜单属性 ...

  5. 《Head First 设计模式》读书笔记——组合模式

    承接上篇博客,我们需要修改所有的菜单,以满足可以添加子菜单,但是我们由于已经把整个项目的框架搭好了,不可能重新实现菜单,所以我们只能修改,那么我们需要做些什么呢? 树形结构,可以容纳菜单.子菜单和菜单 ...

  6. 《Head First 设计模式》读书笔记——模板方法模式

    模板方法模式. 案例 泡茶和冲咖啡的步骤很相似,咖啡的步骤: 把水煮沸 用沸水冲泡咖啡 把咖啡倒进杯子里 加糖和牛奶 泡茶的步骤: 把水煮沸 用沸水浸泡茶叶 把茶倒进杯子 加柠檬 所以咖啡的代码如下: ...

  7. 《深入浅出DPDK》读书笔记(十六):DPDK应用篇(基于DPDK的存储软件优化:SPDK)

    Table of Contents 基于DPDK的存储软件优化 180.基于以太网的存储系统 181.以太网存储系统的优化 SPDK介绍 182.SPDK介绍 (1)兼容性 (2)性能 183.用户态 ...

  8. 《深入浅出DPDK》读书笔记(八):网卡性能优化(异步中断模式、轮询模式、混和中断轮询模式)

    本文内容为读书笔记,摘自<深入浅出DPDK> 82.DPDK的轮询模式 <DPDK PMD( Poll Mode Driver)轮询模式驱动程序> DPDK采用了轮询或者轮询混 ...

  9. 《Head First设计模式》 读书笔记16 其余的模式(二) 蝇量 解释器 中介者

    <Head First设计模式> 读书笔记16 其余的模式(二) 蝇量 解释器 中介者 蝇量(Flyweight Pattern) 如想让某个类的一个实例能用来提供许多"虚拟实例 ...

最新文章

  1. 运维需要掌握的基础知识
  2. ⑨①-成功者的路永远都是相通的
  3. PHP保存Base64图片的问题
  4. 神经网络 | BP神经网络介绍(附源代码:BP神经网络-异或问题)
  5. 字符串大小写字母转换c 语言,towlower()
  6. 前端学习(2758):view基本使用
  7. php js登录,php+js实现单点登录
  8. loadrunner录制回放常见问题及解决办法
  9. 前端开发经验:当初我是如何学习JavaScript
  10. 计算机程序员能做多久,这个行业有年龄限制吗?
  11. python3入门经典100例-Python3入门机器学习_经典算法与应用-慕课网实战
  12. ubuntu系统各pdf编辑器的使用体验和比较
  13. manjaro linux vmware,Manjaro Linux处理vmware的vmmon、vmnet8、Network configuration is missing一堆问题的记录...
  14. GSON处理URL转码
  15. 计算机图形学实验体会,计算机图形学实验报告.doc
  16. 项目时间和本地时间差8小时的问题
  17. 攻略 | 一文教你学会使用GitHub!(附视频)
  18. 浅谈Google分布式文件系统(GFS)
  19. 弹性布局(Flex布局)
  20. 个人博客系列【Hexo】——git 使用ssh协议免密登录

热门文章

  1. 【像程序员一样思考】 读书笔记2
  2. npm package.json文件解读
  3. Bootstrap入门(三十)JS插件7:警告框
  4. linux: convmv =-======pkgs.org
  5. Ubuntu的which、whereis、locate和find命令
  6. 使用GLSL实现雾化的效果
  7. 让FFMPEG支持实时流“伴随”转码
  8. Android的沉浸式状态栏与变色状态栏详解
  9. 基于 Bitbucket Pipeline + Amazon S3 的自动化运维体系
  10. JSTL中fmt标签详解