一、概念
创建简单的对象直接 new 一个就完事,但对于创建时需要各种配置的复杂对象例如手机,没有工厂的情况下,用户需要自己处理屏幕、摄像头、处理器等配置,这样用户和手机就耦合在一起了。
- 可以使代码结构清晰,有效地封装变化:在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
- 对调用者屏蔽具体的产品类:如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
- 降低耦合度:产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
1.1 场景选择
简单工厂通过一个静态方法根据不同的条件生产同一类型的产品,后期每增加一种产品就要去修改静态方法。工厂方法为每一种产品配备一个专用工厂,新增产品时新增一个对应工厂来生产,后期需要生产不同种类的产品会导致类爆炸。抽象工厂根据产品种类配备对应工厂,生产该种类下的不同产品。
| 简单工厂 Simple Factory | 后期不太会新增产品。 |
| 工厂方法 Factory Method | 只生产具体的一类产品。 |
| 抽象工厂 Abstract Factory | 需要生产不同种类的产品。 |
二、简单工厂模式

- 优点:封装了对象的创建,与业务逻辑解耦。
- 缺点:每当具体产品数量增加时,都需要对工厂类进行修改,不符合开闭原则且会越来越臃肿。
| 抽象产品 IProduct | 简单工厂创建的多有对象的父类,负责描述所有实例共有的公共接口。 |
| 具体产品 ConcreteProduct | 简单共厂模式的创建目标。 |
| 简单工厂 SimpleFactory | 负责创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。 |
2.1 抽象产品 (手机)
sealed interface IPhone {
fun show()
}
2.2 具体产品(手机A、手机B)
class PhoneA : IPhone {
override fun show() { println("Phone A") }
}
class PhoneB : IPhone {
override fun show() { println("Phone B") }
}
2.3 简单工厂
//使用枚举,方便对传入的型号做判断
//如果需要传参,可使用密封接口
enum class PhoneModel { A, B }
class SimpleFactory {
companion object {
fun makePhone(phoneModel: PhoneModel): IPhone = when (phoneModel) {
PhoneModel.A -> PhoneA()
PhoneModel.B -> PhoneB()
}
}
}
2.4 使用
val phoneB = SimpleFactory.makePhone(PhoneModel.B)
三、工厂方法模式

- 优点:每当具体产品增加时,只需创建对应的具体工厂即可,对已有代码无修改,符合开闭原则便于扩展。
- 缺点:具体工厂只能生产一种产品。每次增加一个产品时,需增加一个产品类和实现工厂,导致系统中类的个数成倍增加,增加系统复杂度和具体类的依赖。
| 抽象产品 | 工厂方法模式所创建的对象的超类型。也是产品对象的共同父类或者共同拥有的接口。 |
| 具体产品 | 实现了抽象产品角色所定义的接口。某具体产品由具体工厂创建,他们往往一一对应。 |
| 抽象工厂 | 定义了创建抽象产品的方法,任何在模式中创建对象的工厂类都必须实现这个接口。 |
| 具体工厂 | 实现抽象工厂接口的具体工厂类,负责生产具体的产品。 |
3.1 抽象产品(衣服)
sealed interface ICloth {
fun show()
}
3.2 具体产品(外套、牛仔裤)
class Coat : ICloth {
override fun show() { println("夹克") }
}
class Jeans : ICloth {
override fun show() { println("牛仔裤") }
}
3.3 抽象工厂
sealed interface IClothFactory {
fun makeCloth(): ICloth
}
3.4 具体工厂(夹克工厂、牛仔裤工厂)
class CoatFactory : IClothFactory {
override fun makeCloth(): ICloth = Coat()
}
class JeansFactory : IClothFactory {
override fun makeCloth(): ICloth = Jeans()
}
3.5 工厂方法
//使用枚举,方便对传入的型号做判断
//如果需要传参,可使用密封接口
enum class ClothType {
COAT, JEANS
}
class ClothFactory {
companion object {
fun makeCloth(clothType: ClothType) : ICloth = when (clothType) {
ClothType.COAT -> CoatFactory().makeCloth()
ClothType.JEANS -> JeansFactory().makeCloth()
}
}
}
2.6 使用
val coat = ClothFactory.makeCloth(ClothType.COAT)
四、抽象工厂模式

- 优点:每当具体产品族(这里指阿迪或耐克)增加时,只需要创建对应的具体工厂即可,对已有代码无修改,符合开闭原则便于扩展。
- 缺点:每当新增一个系列,需在抽象和具体中同时修改代码。(产品易扩展,品牌难扩展)
4.1 抽象产品(鞋子、衣服)
sealed interface IShoes {
fun show()
}
sealed interface ICloth {
fun show()
}
4.2 具体产品(阿迪鞋子、阿迪衣服、耐克鞋子、耐克衣服)
class AdidasShoes : IShoes {
override fun show() { println("阿迪鞋子") }
}
class AdidasCloth : ICloth {
override fun show() { println("阿迪衣服") }
}
class NikeShoes : IShoes {
override fun show() { println("耐克鞋子") }
}
class NikeCloth : ICloth {
override fun show() { println("耐克衣服") }
}
4.3 抽象工厂
sealed interface IFactory {
fun makeCloth(): ICloth
fun makeShoes(): IShoes
}
4.4 具体工厂(阿迪工厂、耐克工厂)
class AdidasFactory : IFactory {
override fun makeShoes(): IShoes = AdidasShoes()
override fun makeCloth(): ICloth = AdidasCloth()
}
class NikeFactory : IFactory {
override fun makeShoes(): IShoes = NikeShoes()
override fun makeCloth(): ICloth = NikeCloth()
}
4.5 抽象工厂
//当子类没有指定构造和属性时应该定义成 object,因为即便创建多个实例相互之间没有状态区别。
//data object 取代 object 不会打印无用信息
sealed interface ClothType {
sealed interface Nike : ClothType {
data object Cloth : Nike
data object Shoes : Nike
}
sealed interface Adidas : ClothType {
data object Cloth : Adidas
data object Shoes : Adidas
}
}
class Factory {
companion object {
fun makeCloth(clothType: ClothType) = when (clothType) {
ClothType.Adidas.Cloth -> AdidasFactory().makeCloth()
ClothType.Adidas.Shoes -> AdidasFactory().makeShoes()
ClothType.Nike.Cloth -> NikeFactory().makeCloth()
ClothType.Nike.Shoes -> NikeFactory().makeShoes()
}
}
}
4.6 使用
val nikeShoes = Factory.makeCloth(ClothType.Nike.Shoes)
2181

被折叠的 条评论
为什么被折叠?



