zoukankan      html  css  js  c++  java
  • 【原】从头学习设计模式(三)——工厂方法模式

    一、引入

      本章我们来讨论一下工厂方法模式,不同于“简单工厂模式”,工厂方法模式可是23种设计模式中的正规军。下面先引出工厂模式的标准定义。

      工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类说的通俗一点吧,就是把将工厂类抽象成接口,具体的代工厂去实现此接口,同时把产品类也抽象成接口,再构造具体的产品去实现些接口。

      如果你学习了上一章“简单工厂模式”的话,你就能很容易发现,工厂方法模式其实就是把简单工厂中的工厂类进一步抽象,将一个大而全的工厂类拆成若干个互不相干的小工厂类,并且这些小工厂类都继承自最上层最基础的工厂类接口。

    二、工厂模式的类图

      下面给出工厂方法模式的类图结构,有助于理解。

    三、代码示例

      上面的类图中,在灯这个品类下,有灯泡和灯管两种产品,并且都实现了灯的通用方法:关灯和开灯。在工厂类下,有各种生产具体产品的子工厂负责生产相应的两种灯具。

      如果还不是太明白,那我们来假设一个情景。小明(客户端)想要买一个灯泡,他不认识工厂,只能去供销店(工厂类)买,于是和老板说“我要一个灯泡”,老板说 “没问题!您稍等”。转身到了后院,对生产灯泡的小弟(灯泡工厂子类)吆喝一声,给我造个灯泡!不一会灯泡造好了,老板拿给小明,“嘿嘿,灯泡给您作了一个,您试试?”,小明把灯泡拧在灯口上,开关了两下(灯的通用方法)“嘿!挺好,没问题!”,付了钱高高兴兴走了。

    用代码说明就是类似下面这样:

        /// <summary>
        /// 抽象的产品接口
        /// </summary>
        public interface ILight
        {
            void TurnOn();
            void TurnOff();
        }
        /// <summary>
        /// 具体的产品类:灯泡
        /// </summary>
        public class BulbLight:ILight
        {
            public void TurnOn()
            {
                Console.WriteLine("BulbLight turns on.");
            }
    
            public void TurnOff()
            {
                Console.WriteLine("BulbLight turns off.");
            }
        }
        /// <summary>
        ///  具体的产品类:灯管
        /// </summary>
        public class TubeLight:ILight
        {
            public void TurnOn()
            {
                Console.WriteLine("TubeLight turns on.");
            }
    
            public void TurnOff()
            {
                Console.WriteLine("TubeLight turns off.");
            }
    
        }
    
        /// <summary>
        /// 抽象的工厂类
        /// </summary>
        public interface ICreator
        {
            ILight CreateLight();
        }
        /// <summary>
        /// 具体的工厂类:灯泡工厂
        /// </summary>
        public class BulbCreator:ICreator
        {
            public ILight CreateLight()
            {
                return new BulbLight();
            }
    
        }
        /// <summary>
        /// 具体的工厂类:灯管工厂
        /// </summary>
        public class TubeCreator:ICreator
        {
            public ILight CreateLight()
            {
                return new TubeLight();
            }
        }
            /// <summary>
            /// 客户端调用
            /// </summary>
            /// <param name="args"></param>
            static void Main(string[] args)
            {
                //先给我来个灯泡
                ICreator creator = new BulbCreator();
                ILight light = creator.CreateLight();
                light.TurnOn();
                light.TurnOff();
    
                //再来个灯管看看
                creator = new TubeCreator();
                light = creator.CreateLight();
                light.TurnOn();
                light.TurnOff();
    
            }

    四、总结

      LZ认为应用工厂方法模式有以下的几点好处:

      首先,代码结构清晰,装封良好,客户端调用只需要知道具体的工厂类名称即可(如果命名非常规范,则只需要知道产品名称就够了),根本不用关心创建对象的复杂过程(示例中的代码是很简单的,但实际应用中创建和构造对象的过程可能会非常复杂),减少了模块的耦合度。

      其次,符合了“开放-关闭原则”的要求,在增加新产品的情况下,无需修改现有的产品类和工厂类,只要追加新的产品类和工厂类就够了,系统的扩展性得到很大提升。这也弥补了“简单工厂模式”的对修改开放的诟病。

      再次,屏蔽了上层调用者和具体产品实现的牵连。不管产品的实现如何变化,只要接口不变,上层调用都不会跟着变化,只要修改相应的产品类或者产品工厂就够了。

      最后,工厂方法模式还满足了迪米特原则,依赖倒转原则,里氏替换原则,是典型的解耦框架。

  • 相关阅读:
    Log4J日志整合及配置详解
    SmartGit/Hg 4.0.1 发布
    Test Kitchen 0.7.0支持在OpenStack上对Opscode Chef进行集成测试
    RubyGNOME2 1.2.0 发布,支持 GTK+ 3
    PowerDNS Recursor 3.5 RC1 发布
    用于展现图表的50种JavaScript库
    Lambda表达式现状分析
    Node.js 0.8.18 / 0.9.7 发布
    CRUX 3.0 发布,轻量级 Linux 发行版
    Google 更新浏览器内的手写识别技术
  • 原文地址:https://www.cnblogs.com/ytaozhao/p/3389883.html
Copyright © 2011-2022 走看看