工厂三姐妹——工厂方法模式

  简单工厂模式虽然简单,但存在一个很严重的问题。当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背“开闭原则”,如何实现增加新产品而不影响已有代码?工厂方法模式应运而生~

概念

  定义一个用于创建对象的接口,让子类决定将哪一个类实例化,工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式或多态工厂模式。


  在工厂方法模式结构图中包含如下几个角色:
       ● Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
       ● ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
       ● Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
       ● ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。


代码展示

  课本上的例子是大学生学雷锋做好事,照顾孤寡老人

<span style="font-family:KaiTi_GB2312;font-size:18px;">//雷锋类
    class LeiFeng
    {
        public void Sweep()
        {
            Console.WriteLine("扫地");
        }
        public void Wash()
        {
            Console.WriteLine("洗衣");
        }
        public void BuyRice()
        {
            Console.WriteLine("买米");
        }
    }


    //学雷锋的大学生类
    class Undergraduate:LeiFeng
    { 
    }


    //社区志愿者类
    class Volunteer:LeiFeng
    {
    }


    //简单雷锋工厂
    class SimpleFactory
    {
        public static LeiFeng CreateLeiFeng(string type)
        {
            LeiFeng result = null;
            switch (type)
            {
                case "学雷锋的大学生":
                    result = new Undergraduate();
                    break;
                case "社区志愿者":
                    result = new Volunteer();
                    break;
            }
            return result;
        }
    }


     //雷锋工厂
    interface IFactory
    {
        LeiFeng CreateLeiFeng();
    }


    //学雷锋的大学生工厂
    class UndergraduateFactory:IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Undergraduate();
        }
    }


    //社区志愿者工厂
    class VolunteerFactory:IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Volunteer();
        }
    }
</span>

  客户端代码

<span style="font-family:KaiTi_GB2312;font-size:18px;">class Program
    {
        static void Main(string[] args)
        {
            //基本方式:薛磊风代表大学生学习雷锋
            LeiFeng xueleifeng = new Undergraduate();

            xueleifeng.BuyRice();
            xueleifeng.Sweep();
            xueleifeng.Wash();

            LeiFeng student1 = new Undergraduate();
            student1 .BuyRice ();
            LeiFeng student2 = new Undergraduate();
            student2.Sweep();
            LeiFeng student3 = new Undergraduate();
            student3.Wash();

            //工厂方法模式
            IFactory factory = new UndergraduateFactory();
            LeiFeng student = factory.CreateLeiFeng();

            student.BuyRice();
            student.Sweep();
            student.Wash();
        }
    }</span>

结合代码看图说话

  结合代码和结构图我们会发现,大家做的事情是一样的——学雷锋,但是学雷锋这件事的执行者的身份却是不同的,一类是大学生,一类是社区志愿者。所以,当我们需要其他身份的人来做这件事的时候,只需要添加相应的工厂和类即可,有一种打包后成对组合添加的感觉,这样就不会影响已有的类了,大家共用雷锋工厂这个接口达到自己做好事的目的~

小结

1. 主要优点
       工厂方法模式的主要优点如下:
       (1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
       (2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。
       (3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
 
      2. 主要缺点
     工厂方法模式的主要缺点如下:
      (1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
      (2) 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
 
       3. 适用场景
       在以下情况下可以考虑使用工厂方法模式:
       (1) 客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建,可将具体工厂类的类名存储在配置文件或数据库中。
       (2) 抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

我的理解

   工厂方法模式很像是公司管理,最高级领导给各个部门(模块)打开了权限(接口),说明了共同的奋斗目标,各个部门之间是相互独立的,人事变动不会影响其他部门,且各部门的职责是不变的,若是公司需要有新的业务,添加相应的并列部门就好了,添加的部门再根据自己的职责划分子部门(子模块),即可避免了“乾坤大挪移”的状况,自我感觉这就是工厂方法模式的思想——打包。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值