设计模式-抽象工厂模式

引进抽象工厂模式

  每一个模式都是针对一定问题的解决方案。抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。

  在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。(内容转发此文章)

基本介绍 

  1. 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
  2. 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
  3. 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)
  4. 将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现工厂子类。我们可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

例子

我们以pizza店的例子来看看,分不同地区和不同口味来订购pizza。

类图设计:

 

@startuml

abstract class Pizza{
 + {abstract} void prepare()
 + void bake()
 + void cut()
 + void box()
}
class BJCheesePizza{
 + {abstract} void prepare()
}
class BJPepperPizza{
 + {abstract} void prepare() 
}
class GZCheesePizza{
  + {abstract} void prepare()
}
class GZPepperPizza{
  + {abstract} void prepare()
}
Pizza <|-- BJCheesePizza
Pizza <|-- BJPepperPizza
Pizza <|-- GZCheesePizza
Pizza <|-- GZPepperPizza

interface AbsFactory{
 + Pizza createPizza()
}

class BJFactory{
 + Pizza createPizza()
}

class GZFactory{
 + Pizza createPizza()
}

AbsFactory <-- BJFactory
AbsFactory <-- GZFactory

BJCheesePizza <.. BJFactory
BJPepperPizza <.. BJFactory

GZCheesePizza <.. GZFactory
GZPepperPizza <.. GZFactory

class OrderPizza{
}

AbsFactory --o OrderPizza

@enduml

 

生成的类图

 

 

代码

 

package Factory.AbsFactory

/**
 * 抽象工作模式的抽象层
 * */
interface AbsFactory {
    fun createPizza(orderType: String): Pizza?
}

 

package Factory.AbsFactory

abstract class Pizza {

    protected var name:String=""

    abstract fun prepare()

    fun bake(){
        println("$name baking")
    }

    fun cut(){
        println("$name cutting")
    }

    fun box(){
        println("$name boxing")
    }
}
package Factory.AbsFactory

class BJCheesePizza : Pizza() {

    override fun prepare() {
        name = "Beijing Cheese pizza"
        println("preparing BeJin Cheese pizza")
    }
}
package Factory.AbsFactory

class BJPepperPizza : Pizza() {

    override fun prepare() {
        name = "Beijing Pepper pizza"
        println("preparing BeJin Pepper pizza")
    }
}
package Factory.AbsFactory

class GZCheesePizza : Pizza() {

    override fun prepare() {
        name = "GZ Cheese pizza"
        println("preparing GZ Cheese pizza")
    }
}
package Factory.AbsFactory

class GZPepperPizza : Pizza() {

    override fun prepare() {
        name = "GZ Pepper pizza"
        println("preparing GZ Pepper pizza")
    }
}
package Factory.AbsFactory

class BJFactory : AbsFactory {

    override fun createPizza(orderType: String): Pizza? {
        var pizza: Pizza? = null
        when (orderType) {
            "cheese" -> {
                pizza = BJCheesePizza()
            }
            "pepper" -> {
                pizza = BJPepperPizza()
            }
        }
        return pizza
    }
}
package Factory.AbsFactory

class GZFactory : AbsFactory {

    override fun createPizza(orderType: String): Pizza? {
        var pizza: Pizza? = null
        when (orderType) {
            "cheese" -> {
                pizza = GZCheesePizza()
            }
            "pepper" -> {
                pizza = GZPepperPizza()
            }
        }
        return pizza
    }
}
package Factory.AbsFactory

class OrderPizza constructor(factory: AbsFactory, orderType: String) {

    var factory: AbsFactory? = null
    var orderType = ""

    init {
        this.factory = factory
        this.orderType = orderType
        val pizza = factory.createPizza(orderType)
        if (pizza != null) {
            pizza.prepare()
            pizza.bake()
            pizza.cut()
            pizza.box()
        } else {
            println("Order Failure.")
        }
    }
}

运行代码

val orderPizza = OrderPizza(GZFactory(),"cheese")
println("======")
val orderPizza2 = OrderPizza(GZFactory(),"a")
println("======")
val orderPizza3 = OrderPizza(BJFactory(),"pepper")

运行结果

preparing GZ Cheese pizza
GZ Cheese pizza baking
GZ Cheese pizza cutting
GZ Cheese pizza boxing
======
Order Failure.
======
preparing BeJin Pepper pizza
Beijing Pepper pizza baking
Beijing Pepper pizza cutting
Beijing Pepper pizza boxing

 

 

抽象工厂模式的优点

  • 分离接口和实现

   客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。

  • 使切换产品族变得容易

   因为一个具体的工厂实现代表的是一个产品族,比如上面例子的从Intel系列到AMD系列只需要切换一下具体工厂。

 抽象工厂模式的缺点

  • 不太容易扩展新的产品

   如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。

 

posted @ 2019-02-20 11:33  johnny_zhao  阅读(99)  评论(0编辑  收藏  举报