首页 > 其他分享 >05.工厂方法模式

05.工厂方法模式

时间:2023-06-12 09:35:09浏览次数:42  
标签:05 对象 创建 模式 工厂 实现 方法 public

使用工厂方法模式来解决问题

定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method 使一个类的实例化延迟到其子类。

应用工厂方法式来解决问题的思路

工厂方法模式的解决思路很有意思,那就是不解决,采取无为而治的方式:不是需要接口对象吗,那就定义一个方法来创建;可是事实上它自己是不知道如何创建这个接口对象的,没有关系,定义成抽象方法就可以了,自己实现不了,那就让子类来实现,这样这个对象本身就可以只是面向接口编程,而无需关心到底如何创建接口对象了。

工厂方法模式的结构和说明

  • Product: 定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。
  • ConcreteProduct:具体的 Product 接口的实现对象。
  • Creator:创建器,声明工厂方法,工厂方法通常会返回一个 Product 类型的实例对象,而且多是抽象方法。也可以在 Creator 里面提供工厂方法的默认实现,让工方法返回一个缺省的 Product 类型的实例对象。
  • ConcreteCreator:具体的创建器对象,覆盖实现 Creator 定义的工厂方法,返回具体的 Product实例。

示例代码

namespace NetCore3Console.FactoryMethod
{
    /// <summary>
    /// 工厂方法所创建的对象的接口
    /// </summary>
    public interface IProduct
    {
        //可以定义Product的属性和方法
    }

    /// <summary>
    /// 具体的Product对象
    /// </summary>
    public class ConcreteProduct : IProduct
    {
        //实现Product要求的方法
    }

    /// <summary>
    /// 创建器,生命工厂方法
    /// </summary>
    public abstract class Creator
    {
        /// <summary>
        /// 创建Product的工厂方法
        /// </summary>
        /// <returns></returns>
        protected abstract IProduct FactoryMethod();

        public void SomeOperation()
        {
            //通常在这些方法实现中需要调用工厂方法来获取Product对象
            IProduct product = FactoryMethod();
        }

    }

    public class ConcreteCreator : Creator
    {
        protected override IProduct FactoryMethod()
        {
            //重新定义工厂方法,返回一个具体的Product对象
            return new ConcreteProduct();
        }
    }
}

认识工厂方法模式

工厂方法模式的功能

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

这样在设计的时候,不用去考虑具体的实现,需要某个对象,把它通过工厂方法返回就好了,在使用这些对象实现功能的时候还是通过接口来操作,这类似于 IOC/DI的思想。

实现成抽象类

工厂方法的实现中,通常父类会是一个抽象类,里面包含创建所需对象的抽象方法这些抽象方法就是工厂方法。

父类里面,通常会有使用这些产品对象来实现一定的功能的方法,而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行。(也就是说抽象类实现公共功能)

实现成具体的类

也可以把父类实现成为一个具体的类。这种情况下,通常是在父类中提供获取所需对象的默认实现方法,这样即使没有具体的子类,也能够运行。

通常这种情况还是需要具体的子类来决定具体要如何创建父类所需要的对象。也把这种情况称为工厂方法为子类提供了挂钩。通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性。

工厂方法的参数和返回

工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现。也就是说通过在抽象方法里面传递参数,在子类实现的时候根据参数进行选择,看看究竟应该创建哪一个具体的实现对象。

一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体的类的实例。

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

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

客户端应该使用 Creator 对象,或者是使用由 Creator 创建出来的对象。对于客户端使用 Creator 对象,这个时候工厂方法创建的对象,是 Creator 中的某些方法使用,对于使用那些由 Creator 创建出来的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。

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

平行的类层次结构

平行的类层次结构的含义

简单点说,假如有两个类层次结构,其中一个类层次中的每个类在另一个类层次中都有一个对应的类的结构,就被称为平行的类层次结构。

参数化工厂方法(不再用抽象方法)

所谓参数化工厂方法指的就是:通过给工厂方法传递参数,让工厂方法根据参数的不同来创建不同的产品对象,这种情况就被称为参数化工厂方法。当然工厂方法创建的不同的产品必须是同一个 Product 类型的。

public interface IExportFile
    {
        bool Export(string data);
    }

public class ExportOperate
{
    /// <summary>
    /// 导出文件
    /// </summary>
    /// <param name="type"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public bool Export(int type, string data)
    {
        //使用工厂方法
        IExportFile api = FactoryMethod(type);
        return api.Export(data);
    }

    protected IExportFile FactoryMethod(int type)
    {
        IExportFile api = null;
        //根据类型选择创建那种对象
        if (type == 1)
            api = new ExportTxtFile();
        else if (type == 2)
            api = new ExportDB();

        return api;
    }
}

思考工厂方法模式

本质

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

对设计原则的体现

工厂方法模式很好地体现了“依赖倒置原则”。

依赖倒置原则告诉我们“要依赖抽象,不要依赖于具体类”,简单点说就是:不能让高层组件依赖于低层组件,而且不管高层组件还是低层组件,都应该依赖于抽象。

何时选择工厂方法模式

  • 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,这种情况可以选用工厂方法模式,把创建对象的工作延迟到子类中去实现。
  • 如果一个类本身就希望由它的子类来创建所需的对象的时候,应该使用工厂方法模式。

抽象工厂模式和DAO

,采用抽象工厂模式来实现 DAO 的时候,DAOFactory就相当于抽象工厂,里面定义一系列创建相关对象的方法,分别是创建订单主记录的DAO 对象和创建订单子记录的 DAO 对象此时 OrderMainDAO 和 OrderDetailDAO 就相当于被创建的产品,RdbDAOFactory 和XmIDAOFactory 就相当于抽象工厂的具体实现在它们里面会选择相应的具体的产品实现来创建对象。

namespace NetCore3Console.AbstractMethod
{
    /// <summary>
    /// 抽象工厂,创建订单主、自己录对应的DAO对象
    /// </summary>
    public abstract class DaoFactory
    {
        /// <summary>
        /// 创建订单主记录对应的DAO对象
        /// </summary>
        /// <returns></returns>
        public abstract IOrderMainDao CreateOrderMainDao();
        /// <summary>
        /// 创建订单子记录对应的DAO对象
        /// </summary>
        /// <returns></returns>
        public abstract IOrderDetailDao CreateOrderDetailDao();
    }

    /// <summary>
    /// 订单主记录的DAO操作接口
    /// </summary>
    public interface IOrderMainDao
    {
        /// <summary>
        /// 示意方法,保存订单主记录
        /// </summary>
        void SaveOrderMain();
    }

    public interface IOrderDetailDao
    {
        /// <summary>
        /// 示意方法,保存订单子记录
        /// </summary>
        void SaveOrderDetail();
    }

    /// <summary>
    /// 实现主记录、自己录Dao
    /// </summary>
    public class RdbMainDao : IOrderMainDao
    {
        public void SaveOrderMain()
        {
            throw new System.NotImplementedException();
        }
    }
    public class RdbDetailDao : IOrderDetailDao
    {
        public void SaveOrderDetail()
        {
            throw new System.NotImplementedException();
        }
    }

    public class RdbDaoFactory : DaoFactory
    {
        public override IOrderMainDao CreateOrderMainDao()
        {
            return new RdbMainDao();
        }

        public override IOrderDetailDao CreateOrderDetailDao()
        {
            return new RdbDetailDao();
        }
    }
}

抽象工厂模式的优点

  • 分离接口和实现
    客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。
  • 使得切换产品簇变得容易
    因为一个具体的工厂实现代表的是一个产品簇。客户端选用不同的工厂实现,就相当于是在切换不同的产品簇。

思考抽象工厂模式

抽象工厂模式的本质:选择产品簇的实现。

抽象工厂模式的本质

工厂方法是选择单个产品的实现,虽然一个类里面可以有多个工厂方法,但是这些方法之间一般是没有联系的,即使看起来像有联系。
但是抽象工厂着重的就是为一个产品簇选择实现,定义在抽象工厂里面的方法通常是有联系的,它们都是产品的某一部分或者是相互依赖的。如果抽象工厂里面只定义一个方法,直接创建产品,那么就退化成为工厂方法了。

何时选择抽象工厂模式

  • 如果希望一个系统独立于它的产品的创建、组合和表示的时候。换句话说,希望一个系统只是知道产品的接口,而不关心实现的时候。
  • 如果一个系统要由多个产品系列中的一个来配置的时候。换句话说,就是可以动态地切换产品簇的时候。
  • 如果要强调一系列相关产品的接口,以便联合使用它们的时候。

标签:05,对象,创建,模式,工厂,实现,方法,public
From: https://www.cnblogs.com/huiteresa/p/17474094.html

相关文章

  • redis四种模式
    1、单机模式单机模式就是在一台服务器上安装redis,然后启动,所有业务都调用这一台redis服务器。优点:部署简单,只需要在一台服务器上安装并启动redis就行。成本低,没有备用节点,不需要其他的开支。高性能,单机不需要同步数据,数据天然一致性。缺点:可靠性较弱,一旦服务器宕机,所有业务......
  • 005_创建用户账户
     /*一:创建账户1登录2注销3注册二:用户数据1限制访问2关联用户*/ 一:创建账户1登录 2注销 3注册  二:用户数据1限制访问 2关联用户 ......
  • AtCoder Beginner Contest 305 题解
    https://atcoder.jp/contests/abc305/tasks_printE-ArtGalleryonGraph冷知识:md这题赛时没做出来/cy刚看到题:这是什么题啊,\(K,h\)都\(1e5\)能做吗/fn确实能做。考虑类似SPFA的操作。设\(a_x\)表示\(x\)还可以对距离最多为\(a_x\)的点产生贡献,然后就直接......
  • 代理模式的简单理解
    1.废话​ 上次io流联系的时候,有一个地方有待优化,计划使用代理模式。恰逢开始写博客,着闲着也是闲着记录一下丰富一下我的博客记录,之前看过一些网上其他的代理的讲解都很高端,我这技术有限只说一下自己理解的代理模式2.背景​ 之前统计项目中废没在被使用的VUE文件时写了一个遍历......
  • 单例模式(static应用场景)
     单例模式(Singleton) 设计-->一个类只能创建一个对象有效减少内存占用空间 设计一个系统--->百度搜索引擎 publicclassBaidu{ publicvoid搜索(Stringkeyword){ } } 创建一个Baidu对象new 调用搜索的方法做事情方法执行一遍 同一时间有很多很多......
  • VMware Workstation 桥接模式的网卡上让虚拟机使用 VLAN 的正确方法
    要解决的问题有一个虚拟机运行在VMWareworkstation中,如何让这个虚拟机桥接到宿主机的网络上的某个VLAN?常见使用场景只有一个网口的单臂软路由,同时宿主机为Windows,虚拟机软件为VMwareWorkstation,在虚拟机中运行OpenWrt需要在一个网口上,利用VLAN实现虚拟WAN口上的P......
  • C++ 单例模式的各种坑及最佳实践
    单例模式是设计模式中最简单、常见的一种。其主要目的是确保整个进程中,只有一个类的实例,并且提供一个统一的访问接口。常用于Logger类、通信接口类等。基本原理限制用户直接访问类的构造函数,提供一个统一的public接口获取单例对象。这会有一个“先有鸡还是先有蛋”的问题:......
  • 单机下RocketMq安装-多Master模式
    版本:5.1.1官方下载地址:https://rocketmq.apache.org/zh/downloadjdk版本:jdk1.8.0_201在指定目录下新建文件夹rocketmq,并下载安装包到目录下cd/usr/localmkdirrocketmqwgethttps://dist.apache.org/repos/dist/release/rocketmq/5.1.1/rocketmq-all-5.1.1-bin-release.zi......
  • 使用双重检查锁定技术保证多线程中单例模式的线程安全
    使用双重检查锁定技术保证多线程中单例模式的线程安全前言单例模式是一种设计模式,保证一个类只有一个实例,并且在整个应用中共享。它适用于需要控制对共享资源的访问,例如数据库连接、配置文件或日志记录器。但是,在多线程环境下实现单例模式可能比较棘手。如果多个线程同时尝试创......
  • 打开Windows测试模式
    0概述为了在发布前测试Windows驱动,需要在本地计算机上做验证,就需要打开Windows“测试模式”,即TestMode。1步骤关闭“安全启动”,即secureboot;打开“测试模式”,即testmode;安装驱动1.1关闭“安全启动”(secureboot)首先查看计算机是否已开启secureboot,如果未开启,则直......