scala设计模式之工厂模式
一、简介
工厂模式主要是为创建对象提供接口,工厂模式大体可以分为三类:
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