美文网首页
scala设计模式之工厂模式

scala设计模式之工厂模式

作者: 百年叔叔 | 来源:发表于2020-07-06 21:25 被阅读0次

    一、简介

    工厂模式主要是为创建对象提供接口,工厂模式大体可以分为三类:
    1.简单工厂模式(Simple Factory)
    2.工厂方法模式 (Factory Method)
    3.抽象工厂模式 (Abstract Factory)

    二、简单工厂模式

    我以前做过一个排队项目,里面有一个需求是如果排到这位司机了要用微信通知司机轮到他了。但是后续增加了短信通知,电话通知,邮件通知司机所属客户。

    1.首先我们定义一个消息的基类,(接口也可以),这是消息的抽象类。
    /**
     * description: MyMessageFactory 
     * date: 2020/7/6 20:53 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:消息发送的基类
     */
    abstract class MyMessage {
      /**
       * 消息的类型
       */
      def message()
    
    }
    
    2.产品的具体实现

    先来一份短信发送实现(具体的产品类):

    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:短信发送的具体实现
     */
    class SmsMessage extends MyMessage {
      /**
       * 消息的类型
       */
      override def message(): Unit = {
        println("我是短信发送!")
      }
    
    }
    

    微信发消息的具体实现

    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:微信发送消息的实现
     */
    class WeChatMessage extends MyMessage {
      /**
       * 消息的类型
       */
      override def message(): Unit = {
        println("我是微信发送!")
      }
    
    }
    

    邮件发送消息的具体实现

    
    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:邮件发送消息的具体实现
     */
    class MailMessage extends MyMessage {
      /**
       * 消息的类型
       */
      override def message(): Unit = {
        println("我是邮件发送!")
      }
    
    }
    
    3.准备工作完成了,我们来一个简单工厂,消息发送如下:
    
    /**
     * description: MyMessageFactory 
     * date: 2020/7/6 20:58 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:消息发送简单工厂
     */
    object MyMessageFactory {
      //短信
      val SMS: Int = 1
      //微信
      val WECHAT: Int = 2
      //邮件
      val MAIL: Int = 3
    
      def createMessage(i: Int): MyMessage = {
        var mymesage: MyMessage = null
        i match {
          case 1 => mymesage = new SmsMessage
          case 2 => mymesage = new WeChatMessage
          case 3 => mymesage = new MailMessage
        }
        mymesage
      }
    
    }
    
    4.发送消息(我们这里先测试发送邮件)
    /**
     * description: OrderPizza 
     * date: 2020/7/6 18:10 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:发送消息
     */
    object OederMessage {
    
      def main(args: Array[String]): Unit = {
        val m = MyMessageFactory.createMessage(MyMessageFactory.MAIL)
        m.message();
      }
    
    }
    
    image.png
    5.总结

    1.简单工厂是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。
    2.create()方法通常是静态的,所以也称之为静态工厂。
    缺点:
    1 扩展性差(我想增加一种消息发送方式,除了新增一个消息发送类,还需要修改工厂类方法)
    2 不同的产品需要不同额外参数的时候 不支持。

    二、工厂方法模式

    1.模式描述

    提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。

    2.模式作用

    可以一定程度上解耦,消费者和产品实现类隔离开,只依赖产品接口(抽象产品),产品实现类如何改动与消费者完全无关。

    可以一定程度增加扩展性,若增加一个产品实现,只需要实现产品接口,修改工厂创建产品的方法,消费者可以无感知(若消费者不关心具体产品是什么的情况)。
    可以一定程度增加代码的封装性、可读性。清楚的代码结构,对于消费者来说很少的代码量就可以完成很多工作。
    另外,抽象工厂才是实际意义的工厂模式,工厂方法只是抽象工厂的一个比较常见的情况。

    3.适用场景

    消费者不关心它所要创建对象的类(产品类)的时候。

    消费者知道它所要创建对象的类(产品类),但不关心如何创建的时候。

    例如:hibernate里通过sessionFactory创建session、通过代理方式生成ws客户端时,通过工厂构建报文中格式化数据的对象。

    4.模式要素

    提供一个产品类的接口。产品类均要实现这个接口(也可以是abstract类,即抽象产品)。
    提供一个工厂类的接口。工厂类均要实现这个接口(即抽象工厂)。
    由工厂实现类创建产品类的实例。工厂实现类应有一个方法,用来实例化产品类。

    5.实例代码

    首先我们定义一个工厂

    /**
     * description: IMyMessageFactory 
     * date: 2020/7/7 8:23 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:工厂方法模式_工厂接口
     */
    trait IMyMessageFactory {
    
      def createMessage(messageType:Int):IMyMessage
    
    }
    

    接着定义工厂的实现

    
    /**
     * description: MyMessageFactory 
     * date: 2020/7/6 20:58 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:消息发送工厂的实现
     */
    object MyMessageFactory extends IMyMessageFactory {
    
      //短信
      val SMS: Int = 1
      //微信
      val WECHAT: Int = 2
      //邮件
      val MAIL: Int = 3
    
    
      override def createMessage(messageType: Int): IMyMessage = {
    
        // 这里的方式是:消费者知道自己想要什么产品;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。
        var myMessage: IMyMessage = null
        var messageParam: Map[String, String] = Map()
        // 根据某些条件去选择究竟创建哪一个具体的实现对象,条件可以传入的,也可以从其它途径获取。
        messageType match {
          case 1 => myMessage = new SmsMessage; messageParam += ("SMS" -> "13318578765")
          case 2 => myMessage = new WeChatMessage; messageParam += ("WECHAT" -> "bainianshushu")
          case 3 => myMessage = new MailMessage; messageParam += ("EMAIL" -> "test@test.com")
          case _ => myMessage = new MailMessage; messageParam += ("EMAIL" -> "test@test.com")
        }
        myMessage.setMessageParam(messageParam)
        myMessage
      }
    }
    

    接着定义产品的接口

    /**
     * description: IMyMessage 
     * date: 2020/7/7 8:26 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:产品接口
     */
    trait IMyMessage {
      
      def getMessageParam:Map[String,String]
    
      def setMessageParam(messageParam:Map[String,String])
    
      // 发送通知/消息
      def sendMessage(str:String)
    }
    

    虚拟产品类

    /**
     * description: MyAbstractMessage 
     * date: 2020/7/7 8:25 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:虚拟产品类
     */
    abstract class MyAbstractMessage extends IMyMessage {
    
      // 这里可以理解为生产产品所需要的原材料库。最好是个自定义的对象,这里为了不引起误解使用Map。
      var messageParam: Map[String, String] = _
    
    
      override def getMessageParam: Map[String, String] = messageParam
    
      override def setMessageParam(messageParam: Map[String, String]): Unit = {
    
        this.messageParam = messageParam
    
      }
    }
    

    短信产品

    
    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:短信发送的具体实现
     */
    class SmsMessage extends MyAbstractMessage  {
      /**
       * 定义发送短信的方法
       */
      override def sendMessage(str:String): Unit = {
    
        if (null == getMessageParam || null == getMessageParam.get("SMS") || "".equals(getMessageParam.get("SMS").getOrElse())) {
          throw new Error("发送短信,需要传入接收人参数")
        }
    
        printf("我是企业号码 %s 发送短信,我正在给 %s 发送短信 \n",getMessageParam.get("SMS").getOrElse(),str)
      }
    
    }
    

    微信产品

    
    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:微信发送消息的实现
     */
    class WeChatMessage extends MyAbstractMessage  {
      /**
       * 定义发送微信的方法
       */
      override def sendMessage(str:String): Unit = {
    
        if (null == getMessageParam || null == getMessageParam.get("WECHAT") || "".equals(getMessageParam.get("WECHAT").getOrElse())) {
          throw new Error("发送微信,需要传入EMAIL参数")
        }
    
        printf("我是企业号码 %s 发送微信,我正在给 %s 发送微信 \n",getMessageParam.get("WECHAT").getOrElse(),str)
      }
    
    }
    

    邮件产品

    
    /**
     * description: SmsMessage 
     * date: 2020/7/6 20:55 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:邮件发送消息的具体实现
     */
    class MailMessage extends MyAbstractMessage {
    
      /**
       * 定义发送邮件的方法
       */
      override def sendMessage(str:String): Unit = {
    
        if (null == getMessageParam || null == getMessageParam.get("EMAIL") || "".equals(getMessageParam.get("EMAIL").getOrElse())) {
          throw new Error("发送邮件,需要传入EMAIL参数")
        }
        printf("我是企业号码 %s 发送邮件,我正在给 %s 发送邮件 \n",getMessageParam.get("EMAIL").getOrElse(),str)
      }
    }
    

    最后我们来一个消费者

    /**
     * description: OrderPizza 
     * date: 2020/7/6 18:10 
     * version: 1.0
     *
     * @author 阳斌
     *         邮箱:1692207904@qq.com 
     *         类的说明:工厂方法模式_消费者类
     */
    object MyFactoryMethodMain {
    
      def main(args: Array[String]): Unit = {
        val m: IMyMessageFactory = MyMessageFactory
        var myMessage: IMyMessage = null
        // 对于这个消费者来说,不用知道如何生产message这个产品,耦合度降低
    
        // 先来一个短信通知
        myMessage = m.createMessage(MyMessageFactory.SMS)
        myMessage.sendMessage("18614234421")
        //邮件通知
        myMessage = m.createMessage(MyMessageFactory.MAIL)
        myMessage.sendMessage("163@163.com")
        //微信通知
        myMessage = m.createMessage(MyMessageFactory.WECHAT)
        myMessage.sendMessage("bainian")
    
      }
    
    }
    

    结果


    image.png

    相关文章

      网友评论

          本文标题:scala设计模式之工厂模式

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