开发者学堂课程【Scala 核心编程 - 进阶:抽象工厂模式】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/610/detail/9134
抽象工厂模式
内容介绍:
一、基本介绍
二、抽象工厂模式应用实例
三、工厂模式小结
一、基本介绍
1)抽象工厂模式:定义了一个 trait 用于创建相关或有依赖关系的对象簇,而无需指明具体的类
2)抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
3)从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
4)将工厂抽象成两层,AbsFactory (抽象工厂)和具体实现的工厂子类,可以将常规化的操作交给 AbsFactory。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
二、抽象工厂模式应用实例
源码
项目结构
先做一个抽象工厂的 trait,里面声明了一个 create pizza,有很多的工厂去实现这个方法,比如北京的工厂就去实现北京的披萨,伦敦的工厂就去创建伦敦的披萨,这是第一个改进。
第二个改进是在使用上做的改进,在订披萨的时候,不需要再区分是要订北京pizza还是伦敦披萨,因为工厂已经可以明确出来客户想要订购的披萨。
使用抽象工厂模式来完成披萨项目.
class BJFactory extends AbsFactory {
override def createPizza(t: String):
pizza.Pizza = {
var pizza: Pizza= null
if (tequals("chee
se
")) {
pizza = new BJCheesePizza
} else if (t equals("pepper")) {
pizza = new BJPepperPizza
}
return pizza
//还有一个LDFactory开发和BJFactory类似.
//声明一个特质,类似java的接口
trait AbsFactory {
//一个抽象方法
def createPizza(t : String ): Pizza
}
object PizzaStore extends App {
val orderPizza =
new OrderPizza(new BJFactory)
//val orderPizza =
// new OrderPizza(new LDFactory)
println("退出程序...")
}
//orderPizza, 当使用抽象工厂模式后,订购一个 Pizza思路
//1.接收一个子工厂实例,很据该工厂的创建要求去实例
现在是想要订购一个披萨,需要传递一个工厂出来,不管工厂是什么。
把类型传给工厂,工厂就需要知道客户是想要什么类型的pizza,因为工厂已经明确知道是哪个地方的工厂,所以在订购披萨的时候,如果想要北京pizza就直接给北京工厂即可,这样就会显得更加简洁。
class OrderPizza { //
var absF actory :AbsFactory =
_
def this(absFactory: AbsFactory) {
(原先是传一个tap出来)
//多态
this
breakable {
var orderType: String = null
var pizza: Pizza = null
do {
printIn("请输入pizza的类型,使用抽象工厂模式..")
orderType = Std
I
n.readLine()
//使用简单工厂模式来创建对象.
pizza = absFactory.createPizza(orderType)
if (pizza == null){
break()
pizza.prepare()
pizza.bake()
pizza.cut()
pizza.box()
} while (true)
}}}
用的时候整个思路会变得不一样,当去订购披萨时它会传一个工厂,但是是以抽象工厂来接收的,他可能是北京工厂,也有可能是伦敦工厂,所以使用abstract factory,可以体现出他的多态,用抽象工厂的名称调用create pizza。
代码运行:import com . atguigu. chapter17. abstractfactory . pizzastore. pizza. {BICheesePizza,
BJPepperPizza, Pizza}
新建一个包,先写一个抽象工厂类出来,name为AbsFactory,Kind为Trait,随后新建各个地方的工厂,首先,新建一个北京工厂,这工厂需要去继承抽象工厂,然后引一下披萨,北京有胡椒披萨,奶酪披萨等等。
//这时一个实现TAbsFacotory的一个子工厂类
//如果希望订购北京的Pizza就使用该工厂子类
class BJFactory extends AbsFactory {
override def createPizza(t: String): Pizza = {
var pizza: Pizza = nu
l
l
if (t. equals( "
c
heese")) {
pizza = new BICheesePizza
} else if (t.equals("pepper")) {
pizza = new BJPepperPizza
}
return pizza
}
object Pizzastore {
def main(args: Array[String]): Unit = {
new OrderPizza(new BJFactory)
//new Orderpizza(new LBFactory)
}
}
//orderPizza ,当使用抽象工厂模式后,订购一个Pizza思路
//1.接收一个子工厂“实例,根据该工厂的创建要求去实例
object Pizzastore {
def main(args: Array [String]): Unit =
{
new Orderpizza(new BJFactory)
}
三、工厂模式小结
1) 工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
2)三种工厂模式:
简单工厂模式、工厂方法模式和抽象工厂模式
3)设计模式的依赖抽象原则
➢创建对象实例时,不要直接 new 类,而是把这个 new 类的动作放在一个工厂的方法中,并返回。
也有的书上说,变量不要直接持有具体类的引用,因为中间有一个缓冲层,会给一个编写业务逻辑的可能,如果直接new出来,那么就没有缓冲层,不能够进行优化、批量处理或者去做防范工作根本没有机会。代码的控制权交给了底层,就没有办法控制了。但是如果 new 一个工厂里面,在工厂里面是可以添加这些机制的。
➢不要让类继承具体类(依赖抽象),而是继承抽象类或者是trait (接口)
➢不要覆盖基类中已经实现的方法。覆盖和时间是两个概念,覆盖会出现一个问题就是,可能会造成不知道使用的是哪个这种现象。