zoukankan      html  css  js  c++  java
  • 设计模式之工厂方法(三)

    前面一篇已经说了简单工厂,那就趁热打铁,开始讲述工厂方法吧。

    一、引出模式

    开发场景:实现一个导出数据的应用框架,让客户来选择导出数据的方式,并执行真正的数据导出。

    导出数据的方式可以是导出到文本文件,导出到XML,导出到Excel,导出到数据库等。

    好了,我们大概来想一下思路,对于上面的应用框架,导出来的都是一个数据文件,系统并不知道导出的是哪种文件,所以我们可以定义一个统一的导出数据的接口(IDataExport),对于实现导出数据的业务功能对象来说(Client),它应该根据需求来创建相应的IDataExport的实现对象,可是对于实现导出数据的业务功能对象(Client)而已,它并不知道应该创建哪一个IDataExport的实现对象,也不知道如何创建。

    也就是说,客户端是需要创建IDataExport具体的实例对象的,但是客户端只知道IDataExport接口,并不知道具体的实现,那怎么办呢?

    二、认识模式

    1.模式定义

    定义一个创建对象的接口,让子类决定去实例化哪个类,工厂方法使一个类的实例延迟到子类。

    2.解决思路

    在实现数据导出业务对象(Client)里,我们根本不知道该使用哪种导出方式,因此这个对象就不能和具体数据导出对象耦合在一起,它需面对数据导出的接口,但是接口不能直接使用的,需要用到具体的实现对象的实例。

    这样不就矛盾了吗?那怎么办?

    说白了,客户端不就是需要一个具体实现类的对象吗,那好我就用个方法来帮你创建这个实例对象,这个方法自己也不知道它将被用来干嘛,我们可以将这个方法定义成抽象方法,它就当成摆设吧,具体的创建实例的工作就交给它的子类吧,那么这个对象本身就可以只是面对接口编程,而无需关系具体类的创建工作。

    3.模式结构

    IDataExport:定义工厂方法所创建的对象的接口,也就是client需要使用的对象的接口。

    ExportToTxt:具体的IDataExport接口的实现对象。

    IFactoryMethod:创建器,声明工厂方法,工厂方法通常会返回一个IDataExport类型的实例对象,里面大多是抽象方法。也可以提供默认实现。

    CreatForTxt:具体的创建器对象,实现IFactoryMethod定义的工厂方法,返回具体的IFactoryMethod实例。

    4.示例代码

     class Program
        {
            static void Main(string[] args)
            {
    
                //最关键一步,改变了new的对象,也就改变了具体的实现
                IFactoryMethod factory = new CreateForSql();
                IDataExport export = factory.Create();
                export.Export(); 
    
                Console.ReadKey();
            }
        }
    
        #region 工厂
    
        public interface IFactoryMethod
        {
            IDataExport Create();
    
        }
    
        public class CreateForTxt : IFactoryMethod
        {
            public IDataExport Create()
            {
                return new ExportToTxt();
            }
        }
    
        public class CreateForSql : IFactoryMethod
        {
            public IDataExport Create()
            {
                return new ExportToSql();
            }
        }
    
        public class CreateForXml : IFactoryMethod
        {
            public IDataExport Create()
            {
                return new ExportToXml();
            }
        }
        #endregion
    
        #region 产品
    
        public interface IDataExport
        {
            void Export();
        }
    
        public class ExportToTxt : IDataExport
        {
    
            public ExportToTxt()
            {
    
            }
    
            public void Export()
            {
                Console.WriteLine("数据导出到txt");
            }
        }
    
        public class ExportToSql : IDataExport
        {
            public void Export()
            {
                Console.WriteLine("数据导出到数据库");
            }
        }
    
        public class ExportToXml : IDataExport
        {
            public void Export()
            {
                Console.WriteLine("数据导出到xml");
            }
        }
        #endregion 

    三、理解模式

    1.模式功能

    工厂方法模式主要功能是让父类不知道具体实现情况下,完成自身的功能调用;而具体的实现则延迟到子类来实现。

    2.谁来使用工厂方法创建的对象

    事实上,在工厂方法模式里面,应该是IFactoryMethod中的其他方法在使用工厂方法创建的对象,虽然也可以把工厂方法创建的对象直接提供给IFactoryMethod外部使用,但工厂方法的本意,是由IFactoryMethod对象内部的方法来使用工厂方法创建的对象,也就是说,工厂方法一般不提供给IFactoryMethod外部使用。

    1)客户端使用IFactoryMethod对象的情况

     客户端:

    class Program
        {
            static void Main(string[] args)
            {
    
                #region 客户端使用IFactoryMethod对象(推荐)
    
                IFactoryMethod factory = new CreateForSql();
                factory.export();
                #endregion
    
                Console.ReadKey();
            }
        }

    抽象工厂类

     public abstract class IFactoryMethod
        {
            /// <summary>
            /// 抽象方法
            /// </summary>
            /// <returns></returns>
            public abstract IDataExport Create();
    
            /// <summary>
            /// 依赖注入 setter方法
            /// </summary>
            public void export()
            {
                IDataExport export = Create();
                export.Export();
            }
        }

    2)客户端使用由IFactoryMethod创建出来的对象

    这比较好理解,示例代码用的就是这种情况

    客户端

    class Program
    {
            static void Main(string[] args)
            {
    
                #region 客户端使用IFactoryMethod创建的对象(不推荐)
                IFactoryMethod factory = new CreateForSql();
                IDataExport export = factory.Create();
                export.Export(); 
                #endregion
                Console.ReadKey();
         }
    }

    抽象工厂类

    public interface IFactoryMethod
    {
          IDataExport Create();
    }

    小结:在工厂方法模式中,客户端要么使用IFactoryMethod对象,要么使用IFactoryMethod创建的对象,一般客户端不直接使用工厂方法。当然也可以直接把工厂方法暴露给客户端操作,但是一般不这么做。

    3.模式优点

    1)可以在不知具体实现的情况下编程

    工厂方法模式可以让你在实现功能时,如果需要某个产品对象,只需要使用产品的接口即可,而无需关系具体的实现。选择具体的实现的任务延迟到子类去完成。

    2)更容易扩展对象的新版本

    只需要新加入一个子类来提供新的工厂方法实现,然后在客户端使用这个新的子类即可。

    3) 连接平行的类层次结构

    4.模式缺点

    具体产品对象和工厂方法的耦合

    5.模式本质

    工厂方法模式的本质就是延迟到子类来选择实现。

    与简单工厂的区别:从本质上讲,在具体实现上都是“选择实现”,但是简单工厂是直接在工厂类中进行“选择实现”;而工厂方法会把这个工作延迟到子类来实现,工厂类里面的工厂方法是依赖于抽象而不是具体的实现。

    6.模式选择

    1) 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,这种情况可以选用工厂方法模式,把创建对象的工作延迟到子类中去实现。

    2) 如果一个类本身希望由它的子类来创建所需的对象的时候,应该使用工厂方法模式。

  • 相关阅读:
    PHP安装linux
    nginx 安装
    Redis安装
    linux启动http服务
    收藏的有用的网页
    laravel框架部署后有用命令
    .net 报错access to the path c: empimagefilesmsc_cntr_0.txt is denied
    oracle 触发器
    学习Auxre记录
    mysql数据库索引
  • 原文地址:https://www.cnblogs.com/zxj159/p/3412378.html
Copyright © 2011-2022 走看看