本文介绍: 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂模式经常以工厂方法的方式实现。
抽象工厂模式
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂模式经常以工厂方法的方式实现。
模型说明
- 抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
- 具体产品(Concrete Product)是抽象产品的多种不同类型实现。 所有变体(维多利亚/现代)都必须实现相应的抽象产品(椅子/沙发)。
- 抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
- 具体工厂(Concrete Factory)实现抽象工厂的构建方法。 每个具体工厂都对应特定产品变体, 且仅创建此种产品变体。
- 尽管具体工厂会对具体产品进行初始化,其构建方法签名必须返回相应的抽象产品。这样,使用工厂类的客户端代码就不会与工厂创建的特定产品变体耦合。客户端(Client)只需通过抽象接口调用工厂和产品对象,就能与任何具体工厂/产品变体交互。
优缺点
1.优点
- 你可以确保同一工厂生成的产品相互匹配。
- 你可以避免客户端和具体产品代码的耦合。
- *单一职责原则:*你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- *开闭原则:*向应用程序中引入新产品变体时, 你无需修改客户端代码。
2.缺点
- 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
使用场景
如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。
参考代码
在上篇文章的基础上,小米和华为都要生产手表的时候,我们应该怎么编码?
// factory.go
// 抽象工厂,包含一系列创建产品的抽象
type IFactory interface {
makePhone() IPhone
makeWatch() IWatch
}
func GetFactory(tp string) IFactory {
if tp == "xiaomi" {
return &Xiaomi{}
} else if tp == "huawei" {
return &Huawei{}
} else {
panic("not found type")
}
return nil
}
// 具体工厂类
type Xiaomi struct{}
func (x *Xiaomi) makePhone() IPhone {
return &Phone{
name: "xiaomi 12",
price: 3999,
}
}
func (x *Xiaomi) makeWatch() IWatch {
return &Watch{
name: "miWatch",
price: 299,
}
}
type Huawei struct{}
func (h *Huawei) makePhone() IPhone {
return &Phone{
name: "iPhone 14",
price: 6999,
}
}
func (h *Huawei) makeWatch() IWatch {
return &Watch{
name: "apple watch",
price: 2999,
}
}
// product.go
// 抽象产品
type IPhone interface {
setPhoneName(name string)
setPhonePrice(price float64)
getPhoneName() string
getPhonePrice() float64
}
type IWatch interface {
setWatchName(name string)
setWatchPrice(price float64)
getWatchName() string
getWatchPrice() float64
}
// 具体产品类
type Phone struct {
name string
price float64
}
func (g *Phone) setPhoneName(name string) {
g.name = name
}
func (g *Phone) getPhoneName() string {
return g.name
}
func (g *Phone) setPhonePrice(price float64) {
g.price = price
}
func (g *Phone) getPhonePrice() float64 {
return g.price
}
type Watch struct {
name string
price float64
}
func (w *Watch) setWatchName(name string) {
w.name = name
}
func (w *Watch) getWatchName() string {
return w.name
}
func (w *Watch) setWatchPrice(price float64) {
w.price = price
}
func (w *Watch) getWatchPrice() float64 {
return w.price
}
// main.go
// 客户端调用
func main() {
xiaomiFactory := GetFactory("xiaomi")
xiaomiPhone := xiaomiFactory.makePhone()
xiaomiWatch := xiaomiFactory.makeWatch()
huaweiFactory := GetFactory("huawei")
huaweiPhone := huaweiFactory.makePhone()
huaweiWatch := huaweiFactory.makeWatch()
printPhoneDetails(xiaomiPhone)
printWatchDetails(xiaomiWatch)
printPhoneDetails(huaweiPhone)
printWatchDetails(huaweiWatch)
}
func printPhoneDetails(p IPhone) {
fmt.Printf("Phone: %s", p.getPhoneName())
fmt.Println()
fmt.Printf("Price: %.2f", p.getPhonePrice())
fmt.Println()
fmt.Println("---------------------------")
}
func printWatchDetails(w IWatch) {
fmt.Printf("watch: %s", w.getWatchName())
fmt.Println()
fmt.Printf("Price: %.2f", w.getWatchPrice())
fmt.Println()
fmt.Println("---------------------------")
}
output:
Phone: xiaomi 12
Price: 3999.00
---------------------------
watch: miWatch
Price: 299.00
---------------------------
Phone: iPhone 14
Price: 6999.00
---------------------------
watch: apple watch
Price: 2999.00
---------------------------
原文地址:https://blog.csdn.net/ldxxxxll/article/details/135647355
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_58312.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。