设计模式 - 工厂模式 Factory Pattern

部署运行你感兴趣的模型镜像

参考文章

一、概念

创建简单的对象直接 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)

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值