美文网首页设计模式
设计模式 ~ 工厂模式

设计模式 ~ 工厂模式

作者: BTPJ | 来源:发表于2021-11-10 15:40 被阅读0次

    1、简单工厂模式

    • 定义:简单工厂模式又名静态工厂方法模式,是由一个工厂对象决定创建出哪一种产品类的实例,包含:
      • 产品工厂类(Factory):负责生产各种具体的产品,不关心产品产生的过程,只关心要生产的产品的类型
      • 抽象产品类(IProduct):创建的所有对象的父类,它负责描述所有实例所共有的公共接口
      • 具体产品类(Product):具体的产品,封装了产品建造的过程以及使用的教程
    • 简单实现
      • 不同手机型号需要使用不同的推送,可以集成小米、华为、极光推送然后创建一个工厂类根据手机型号来使用不同的推送。
      • 1、定义推送调用的接口
    /**
     * 定义一个通用的push推送接口
     * @author LTP  2021/11/10
     */
    interface IPush {
        /** 定义一个抽象的push方法 */
        fun push()
    }
    
    • 2、封装不同的推送调用方法
    /**
    * 具体产品类:小米推送具体实现
    * @author LTP  2021/11/10
    */
    class MiPush : IPush {
    
       override fun push() {
           println("小米手机使用小米推送")
       }
    }
    
    /**
     * 具体产品类:华为推送具体实现
     * @author LTP  2021/11/10
     */
    class HuaWeiPush : IPush {
    
        override fun push() {
            println("华为手机使用华为推送")
        }
    }
    
    /**
     * 具体产品类:极光推送具体实现
     * @author LTP  2021/11/10
     */
    class JiGuangPush : IPush {
    
        override fun push() {
            println("其他手机使用极光推送")
        }
    }
    
    • 3、创建一个push工厂
    /**
     * 推送工厂类
     * @author LTP  2021/11/10
     */
    object PushFactory {
    
        /**
         * 根据具体的手机类型使用具体的推送服务
         *
         * @param type 推送类型
         * @return Push 具体的推送类型
         */
        fun createPush(type: String): IPush {
            return when (type) {
                "xiaoMi" -> MiPush()
                "huaWei" -> HuaWeiPush()
                else -> JiGuangPush()
            }
        }
    }
    
    • 4、具体使用
    /**
     * 具体调用
     *
     * @author LTP  2021/11/10
     */
    class CreatePush {
    
        companion object {
            @JvmStatic
            fun main(args: Array<String>) {
                PushFactory.createPush("xiaoMi").push()
                PushFactory.createPush("huaWei").push()
            }
        }
    }
    
    执行结果:
    小米手机使用小米推送
    华为手机使用华为推送
    
    • 使用场景与优缺点
      • 使用场景
        • 1、工厂类负责创建的对象比较少。
        • 2、客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心
      • 优点:用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性
      • 缺点:类型在编译期间已经被确定,增加新类型需要修改工厂,违背了开放封闭原则(ASD) ;需要事先知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用

    2、工厂方法模式

    • 定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类,包含:
      • Product:抽象产品类。
      • ConcreteProduct:具体产品类,实现Product接口。
      • Factory:抽象工厂类,该方法返回一个Product类型的对象。
      • ConcreteFactory:具体工厂类,返回ConcreteProduct实例。
    • 简单实现
      • 现在来了一个新需求,在原来基础上oppo手机需加入oppo推送,而且后面可能还会有更多手机厂商的推送...
      • 实现步骤
        • 在原来的基础上加一层抽象工厂类
        /**
         * 推送抽象工厂类
         * @author LTP  2021/11/10
         */
        abstract class AbsPushFactory {
    
              abstract fun <T : IPush> createPush(clazz: Class<T>): T
        }
    
    • 原来的工厂类继承抽象工厂类利用反射来初始化各产品对象
        /**
         * @author LTP  2021/11/10
         */
      object PushFactory : AbsPushFactory() {
    
          override fun <T : IPush> createPush(clazz: Class<T>): T {
               return Class.forName(clazz.name).getDeclaredConstructor().newInstance() as T
        }
    }
    
    • 这是加入跟以前小米华为一样,添加oppo推送的具体产品类......
    /**
     * 具体产品类:Oppo推送具体实现
     * @author LTP  2021/11/10
     */
    class OppoPush : IPush {
    
        override fun push() {
            println("oppo手机使用oppo推送")
        }
    }
    
    • 最终的调用
    /**
     * 具体调用
     * 
     * @author LTP  2021/11/10
     */
    class CreatePush {
    
        companion object {
            @JvmStatic
            fun main(args: Array<String>) {
                PushFactory.createPush(MiPush::class.java).push()
                PushFactory.createPush(HuaWeiPush::class.java).push()
                PushFactory.createPush(OppoPush::class.java).push()
            }
        }
    }
    
    执行结果:
    小米手机使用小米推送
    华为手机使用华为推送
    oppo手机使用oppo推送
    
    • 优点:可以自由新增更多的产品线而不破坏开放封闭原则
    • 缺点:使用反射,多多少少影响性能

    3、抽象工厂模式

    • 定义:为创建一组相关或者相互依赖的对象提供一个接口,而无需指定它们的具体类;
      • AbstractFactory:抽象工厂,它声明了用来创建不同产品的方法。
      • ConcreteFactory:具体工厂,实现抽象工厂中定义的创建产品的方法。
      • AbstractProduct:抽象产品,为每种产品声明业务方法。
      • ConcreteProduct:具体产品,定义具体工厂生产的具体产品,并实现抽象产品中定义的业务方法。
    • 新需求
      • 添加针对向不同的手机厂商发短信
    • 实现
      • 1、添加一个Isend接口
    /**
     * 定义一个通用的发送短信接口
     * @author LTP  2021/11/10
     */
    interface ISend {
        /** 定义一个抽象的send方法 */
        fun send()
    }
    
    • 2、华为小米分别添加对Isend的实现
    /**
     * 具体产品类:小米短信具体实现(华为代码同理已省略)
     * @author LTP  2021/11/10
     */
    class MiSend : ISend {
    
        override fun send() {
            println("小米手机发送小米短信")
        }
    }
    
    • 3、添加包含push和send的抽象工厂
    /**
     * 推送发短信抽象工厂类
     * @author LTP  2021/11/10
     */
    abstract class AbsPushSendFactory {
    
        abstract fun createPush(): IPush
        abstract fun createSend(): ISend
    }
    
    • 4、分别实现华为工厂和小米工厂(代码一样已省略)
    /**
     * 华为工厂类
     *
     * @author LTP  2021/11/10
     */
    class HuaWeiFactory : AbsPushSendFactory() {
    
        override fun createPush(): IPush {
            return HuaWeiPush()
        }
    
        override fun createSend(): ISend {
            return HuaWeiSend()
        }
    }
    
    • 5、具体调用
    /**
     * 具体调用
     *
     * @author LTP  2021/11/10
     */
    class CreatePushSend {
    
        companion object {
            @JvmStatic
            fun main(args: Array<String>) {
                // 小米工厂
                val miFactory = MiFactory()
                miFactory.createPush().push()
                miFactory.createSend().send()
    
                // 华为工厂
                val huaWeiFactory = HuaWeiFactory()
                huaWeiFactory.createPush().push()
                huaWeiFactory.createSend().send()
            }
        }
    }
    
    执行结果:
    小米手机使用小米推送
    小米手机发送小米短信
    华为手机使用华为推送
    华为手机发送华为短信
    
    • 使用场景与优缺点
      • 使用场景
        • 1、一个系统不依赖于产品线实例如何被创建、组合和表达的细节。
        • 2、系统中有多于一个的产品线,而每次只使用其中某一产品线。
        • 3、一个产品线(或是一组没有任何关系的对象)拥有相同的约束。
      • 优点:具体类的创建实例过程与客户端分离,客户端通过工厂的抽象接口操纵实例,客户端并不知道具体的实现是谁。
      • 缺点:增加新的产品族则也需要修改抽象工厂和所有的具体工厂。

    4、总结对比

    • 简单工厂模式:单一产品线固定产品;一个工厂类,无抽象工厂类
    • 工厂模式:单一产品线可延伸产品(添加产品,只需添加IProduct的新产品实现类即可);一个抽象工厂类,所有产品共用一个工厂类
    • 抽象工厂模式:固定多产品线可延伸产品(添加产品,需添加IProduct的新产品实现类以及新产品的工厂类);一个抽象工厂类,每一个产品都有一个工厂类

    相关文章

      网友评论

        本文标题:设计模式 ~ 工厂模式

        本文链接:https://www.haomeiwen.com/subject/cttvzltx.html