​​​Scala设计模式UML图例和代码实现实战 ​ 行为模式 之 策略设计模式

16 篇文章 0 订阅
16 篇文章 2 订阅

 

策略设计模式

在企业应用程序中,具有不同的特定算法实现并在应用程序运行时选择使用一种算法,这是很常见的事情。一些示例可能包括不同的排序算法,这些算法对于不同大小或类型的数据具有不同的性能,对于各种可能的数据表示具有不同的解析器,等等。

策略设计模式使我们能够定义一系列算法并在运行时选择特定算法。

策略设计模式有助于封装,因为每个算法可以单独定义,然后注入使用它的类中。不同的实现也是可互换的。

示例类图对于类图,让我们假设我们正在编写一个需要从文件加载一些数据然后以某种方式使用这些数据的应用程序。当然,数据可以用不同的格式表示(在这种情况下为CSV或JSON),根据文件类型,我们将使用不同的解析策略。表示我们的解析器的类图如下图所示:我们基本上有一个不同类实现的接口,然后根据需要的接口,为PersonApplication注入正确的接口。

前面的类图看起来非常类似于我们之前在本书中看到的桥梁设计模式。即使是这种情况,两种模式都有不同的目的 - 构建器关注结构,而这里只关注行为。此外,策略设计模式看起来更加耦合。

 

 

people.csv 内容:

Ivan,26,London

Maria,23,Edinburgh

John,36,New York

Anna,24,Moscow

 

people.json 内容:

[

{

"name": "Ivan",

"age": 26,

"address": "London"

},

{

"name": "Maria",

"age": 23,

"address": "Edinburgh"

},

{

"name": "John",

"age": 36,

"address": "New York"

},

{

"name": "Anna",

"age": 24,

"address": "Moscow"

}

]

 

前面的数据集都包含完全相同的数据,但这些格式使它们看起来完全不同,并且它们在解析时需要不同的方法。

在我们的例子中我们做了一件额外的事情。 我们使用了工厂设计模式,以便在运行时选择正确的实现,具体取决于文件类型:前面的工厂只是一个例子。 它只检查文件扩展名,当然,可以使其更加健壮。 使用这个工厂,我们可以为要使用的应用程序类选择正确的解析器实现,其代码如下所示:无论实现是什么,应用程序类看起来都是一样的。 可以插入不同的实现,只要没有错误,一切都应该运行。

现在,让我们看看我们如何在我们的示例中使用我们的策略设计模式:

 

case class Person(name: String, age: Int, address: String)

 

import java.io.InputStreamReader

 

import com.github.tototoshi.csv.CSVReader

import com.ivan.nikolov.behavioral.strategy.model.Person

 

import org.json4s._

import org.json4s.jackson.JsonMethods

 

trait Parser[T] {

def parse(file: String): List[T]

}

 

class CSVParser extends Parser[Person] {

override def parse(file: String): List[Person] =

CSVReader.open(new InputStreamReader(this.getClass.getResourceAsStream(file))).all().map {

case List(name, age, address) =>

Person(name, age.toInt, address)

}

}

 

class JsonParser extends Parser[Person] {

implicit val formats = DefaultFormats

override def parse(file: String): List[Person] =

JsonMethods.parse(StreamInput(this.getClass.getResourceAsStream(file))).extract[List[Person]]

}

 

//具体执行策略的地方, 自动根据文件名后缀执行创建相应的解析器.

object Parser {

def apply(filename: String): Parser[Person] =

filename match {

case f if f.endsWith(".json") => new JsonParser

case f if f.endsWith(".csv") => new CSVParser

case f => throw new RuntimeException(s"Unknown format: $f")

}

}

 

class PersonApplication[T](parser: Parser[T]) {

def write(file: String): Unit = {

System.out.println(s"Got the following data ${parser.parse(file)}")

}

}

 

object ParserExample {

def main(args: Array[String]): Unit = {

val csvPeople = Parser("people.csv")

val jsonPeople = Parser("people.json")

val applicationCsv = new PersonApplication(csvPeople)

val applicationJson = new PersonApplication(jsonPeople)

System.out.println("Using the csv: ")

applicationCsv.write("people.csv")

System.out.println("Using the json: ")

applicationJson.write("people.json")

}

}

 

import java.io.InputStreamReader

 

import com.github.tototoshi.csv.CSVReader

import com.ivan.nikolov.behavioral.strategy.model.Person

import org.json4s.{StreamInput, DefaultFormats}

import org.json4s.jackson.JsonMethods

 

class Application[T](strategy: (String) => List[T]) {

def write(file: String): Unit = {

System.out.println(s"Got the following data ${strategy(file)}")

}

}

 

object StrategyFactory {

implicit val formats = DefaultFormats

def apply(filename: String): (String) => List[Person] =

filename match {

case f if f.endsWith(".json") => parseJson

case f if f.endsWith(".csv") => parseCsv

case f => throw new RuntimeException(s"Unknown format: $f")

}

def parseJson(file: String): List[Person] =

JsonMethods.parse(StreamInput(this.getClass.getResourceAsStream(file))).extract[List[Person]]

def parseCsv(file: String): List[Person] =

CSVReader.open(new InputStreamReader(this.getClass.getResourceAsStream(file))).all().map {

case List(name, age, address) =>

Person(name, age.toInt, address)

}

}

 

object StrategyExample {

def main(args: Array[String]): Unit = {

val applicationCsv = new Application[Person](StrategyFactory("people.csv"))

val applicationJson = new Application[Person](StrategyFactory("people.json"))

 

System.out.println("Using the csv: ")

applicationCsv.write("people.csv")

 

System.out.println("Using the json: ")

applicationJson.write("people.json")

}

}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心自由天使

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值