开发者学堂课程【Scala 核心编程 - 进阶:简单工厂模式】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/610/detail/9132
简单工厂模式
内容介绍:
一、基本介绍
二、看一个具体的需求
三、传统方式
四、传统的方式的优缺点
五、使用简单工厂模式
一、基本介绍
1)简单工厂模式是属于创建型模式,但不属于23种GOF设计模式之一。
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
2)简单工厂模式:
定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
3)在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.
二、看一个具体的需求
设计模式的好坏是相对而言的,想要说一个模式好,首先要去看一下他传统是怎么解决的,然后进行对比发现模式的好坏,没有对比,很难发现它的妙用。
看一个披萨的项目:要便于披萨种类的扩展,要便于维护,完成披萨订购功能。
披萨簇的设计,
假如定义一个抽象的披萨,里面有四个方法,首先是准备原材料 Prepare,Bake 是烘制,Cut 是切割,Box 就是打包。
这就意味着,制作一个披萨需要四个流程,披萨也有不同种类的披萨,例如有Greek pizza 希腊披萨,Cheese pizza 是奶酪披萨,也会有更多类型的披萨,基于此完成一个设计。
理解需求是要做一个披萨店,披萨店里面有各种种类的披萨,设计需要支持创建各种披萨,同时还要完成订购功能,订购披萨里面肯定要有创建披萨。
三、传统方式
abstract class Pizza {//写
(抽象出来披萨,因为不知道将来有多少种披萨)
var name:String =
_
//假定,每种pizza 的准备原材料不同,因此做成抽象的.切割打包烘培可以看做是一样的,其中,准备原材料是不一样的,比如想要制作的希腊披萨可能是一种原材料,而可能胡椒披萨准备的是另一些原材料,奶酪披萨准备的原材料也是不一样的,所以需要抽象出来.
def prepare()
def cut(): Unit = {
println(this.name + " cutting ..")
}
def bake(): Unit = {
println(this.name + " baking ..")
}
def box(): Unit = {
println(this.name + " boxing ..")
}
}
class GreekPizza extends Pizza{
//
写
override def prepare(): Unit = {
this.name ="希腊pizza"
println(this.name + " preparing..")
}}
class PepperPizza extends Pizza {
//
写override def prepare(): Unit = {
this.name ="胡椒pizza"
println(this.name + " preparing..")
}}
object PizzaStore extends App {
//
写测试程序
val orderPizza = new OrderPizza
println("退出程序....")
}
//订购
import scala.io.StdIn
import scala.ut
l contrc.Breaks,
import scala.io.Stdln
class OrderPizza {
var orderType:String =
(订购披萨的种类)
var pizza:Pizza =-
breakable {
do {
//循环自此开始
println("请输入pizza的类型")
orderType = StdIn.readLine(
if (orderType.equals("greek")
){
//创建pizza
this.pizza = new GreekPizz
a
}else if (orderType.equals("
pepper
”
})(
//创建pizza
this.pizza = new PepperPi
z
z
a
}else {
break()
}
this.pizza.prepare()
this.pizza.bake()
this.pizza.cut()
this.pizza.box()
}while (true)
}
}
object PizzaStore extends App {//写测试程序
val orderPizza = new OrderPizz
printIn("退出
程序
...”
)
创建一个新的包,名字为 Pizzastore,在这个里面还要新建两个包,一个是专门管理披萨的使用,名字为 pizza。另外一个是包名为 pizzastoreorder。
//假定,每种 pizza 的准备原材料不同,因此做成抽象的.
首先先定义两种披萨,第一个是 greek pizza,让它去继承披萨,写完以后要去重写方法,赋予这个 pizza名字,然后输出一句话就是,这份披萨正在准备。
class GreekPizza extends Pizza {
override def prepare(): Unit = {
this.name ="希腊pizza"
println(this .name +"preparing" )
与此同时,再建一个pepper pizza,首先让它继承一下披萨,程序里面把希腊名字改成胡椒即可,有了两种披萨以后就去order里面写订披萨的方法。
class orderPizza {
var orderType: string =_
var pizza: Pizza =_
breakable {
do {
Print
ln(
"请输入pizza的类型" )
orderType = stdIn. readLine( )
if (orderType . equals("greek")) {
//创建pizza
this.pizza = new GreekPizza
} else if (orderType . equals("pepper")) {
//创建pizza
this.pizza = new PepperPizza
} else {
break()
this .pizza. prepare()
this.pizza . bake()
this .pizza.cut()
this.pizza. box( )
} while (true)
在older里面新建一个Pizzastore
object Pizzastore {
def main(args: Array [String]): Unit = {
new OrderPizza
运行以后就会说出一句"请输入披萨的类型",然后输入greek,然后系统就会出现希腊披萨正在准备,正在哄制,正在切割,正在打包四句话。
四、传统的方式的优缺点
1)优点是比较好理解,简单易操作。
2)缺点是违反了设计模式的ocp原则,即对拉展开放,对修改关闭。即当给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
3)比如我们这时要新增加一个Pizza的种类(Cheese披萨),我们需要做如下修改.
//新增写
class CheesePizza extends Pizza{
override def prepare(): Unit = {
this.name="奶酿pizza"
println(this.name + " preparing..")
}
}
//增加一段代码OrderPizza.scala
//
写do {
println("请输入pizza的类型")
orderType = Stdln.readLine(if (orderType.equals("greek")) {
his.pizza=new GreekPizza
} else if (orderType.equals("cheese")) {
this.pizza = new CheesePizza
else {
break()
}
order披萨部分中新加入一段代码在此订购部分加一段代码,在未来开发过程中可能会出现销售披萨的部分SalePizza,假设客户说要一份胡椒披萨,因为不是从工厂里面取的,就意味着又要把逻辑再重新写一遍才行,产生一个披萨,不是从工厂取的,没有把代码封装起来,这种逻辑在很多地方都有可能遇到,这就意味着未来在涉及到这种逻辑的时候,就都要去进行写,如果出现了一段代码,完全可以不用写工厂模式,但是将来产生披萨的场景会很多很多,可能有销售、购买、打包或者批发等等,那就会比较麻烦,这个逻辑就会越改越乱。
4)改进的思路分析
分析:修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizza的代码,往往有多处。
思路:把创建Pizza对象封装到一个类中,这样有新的Pizza种类时,只需要修改该类就可,其它有创建到Pizza对象的代码就不需要修改了.-> 简单工厂模式
五、使用简单工厂模式
1)简单工厂模式的设计方案:定义一个实例化Pizaa对象的类,封装创建对象的代码。
2)看代码示例
class simplePizzaFactory { //写
//说明。
//提供了一个创建pizza的方法,有需要创建pizza调用该方法即可。
def createPizza(t: String): Pizza = {
var pizza: Pizza = nu1l
if (t.equals("greek")) {
pizza = new GreekPizza
} else if (t.equals("pepper")) {
pizza = new PepperPizza
} else if (t.equals("cheese")) {
pizza = new CheesePizza
}
return pizaa
如果真的有披萨增加了,那就只需要改一个地方就可以,是greak就返回greekpizza,是 pepper 就返回 papperpizza,是 cheese 就返回 cheesepizza。
Var
order
Pizzat : string ={
var pizza
:
Pizza =
_
//使用简单工广模式来创建对象
breakable {
do {
println("请输入pizza的类型")
orderType = stdIn. readLine( )
pizza = SimpleFactory . createPizza( orderType )
if (pizza;==nu
ll
) {
break()
}
this .pizza. prepare()
this .pizza. bake( )
this.pizza.cut()
this .pizza. box()
} while (true)
运行如下:
请输入 pizza 的类型使用简单工厂模式~~
pepper
胡椒pizza preparing
胡椒pizza baking ..
胡椒pizza cutting ..
胡椒pizza boxing
请输入pizza的类型使用简单工厂模式~
greek
希腊pizza preparing
希腊pizza baking ..
希腊pizza cutting ..
希腊pizza boxing .
请输入pizza的类型使用简单工厂模式~.
By
p
rocess finished with exit code
0
如果再有披萨的改动,添加代码不是修改,只需要在simple factory改动即可.