[go] 工厂方法模式
工厂方法模式
工厂方法模式是一种创建型设计模式,定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。让类把实例化推迟到子类。
模型说明
-
Product:
- 将会对接口进行声明。对于所有由创建者及其子类构件的对象,这些接口都是通用的。
-
ConcreteProductA,ConcreteProductB:
- 具体产品是产品接口的不同实现。
-
Creator:
- 声明返回产品对象的工厂方法。该方法的返回类型必须与产品接口相匹配。
- 可以将工厂方法声明为抽象方法,强制要求每个子类以不同方式实现该方法。或者可以在基础工厂方法中返回默认产品类型。
-
ConcreteCreatorA,ConcreteCreatorB:将会重写基础工厂方法,使其返回不同类型的产品。
优缺点
1.优点
- 你可以避免创建者和具体产品之间的紧密耦合。
- 单一职责原则:你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
- 开闭原则:无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。
2.缺点
- 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。
使用场景
- 当你在编写代码的过程中, 如果无法预知对象确切类别及其依赖关系时, 可使用工厂方法。
- 如果你希望用户能扩展你软件库或框架的内部组件, 可使用工厂方法。
- 如果你希望复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法。
参考代码
假设我们需要生产不同的手机
// 产品接口
type IPhone interface {
setName(name string)
setPrice(price float64)
getName() string
getPrice() float64
}
// 具体产品
type Phone struct {
name string
price float64
}
func (g *Phone) setName(name string) {
g.name = name
}
func (g *Phone) getName() string {
return g.name
}
func (g *Phone) setPrice(price float64) {
g.price = price
}
func (g *Phone) getPrice() float64 {
return g.price
}
type Xiaomi struct {
Phone
}
func NewXiaomi() IPhone {
return &Phone{
name: "xiaomi",
price: 1999,
}
}
type Huawei struct {
Phone
}
func NewHuawei() IPhone {
return &Phone{
name: "huawei",
price: 4999,
}
}
// 工厂方法
func getPhone(phoneType string) (IPhone, error) {
if phoneType == "xiaomi" {
return NewXiaomi(), nil
}
if phoneType == "huawei" {
return NewHuawei(), nil
}
return nil, fmt.Errorf("wrong phone type passed")
}
// 客户端执行
func main() {
xiaomi, err := getPhone("xiaomi")
if err != nil {
panic(err)
}
huawei, err := getPhone("huawei")
if err != nil {
panic(err)
}
printDetails(xiaomi)
printDetails(huawei)
}
func printDetails(p IPhone) {
fmt.Printf("Phone: %s", p.getName())
fmt.Println()
fmt.Printf("Price: %.2f", p.getPrice())
fmt.Println()
fmt.Println("---------------------------")
}
输出:
Phone: xiaomi
Price: 1999.00
---------------------------
Phone: huawei
Price: 4999.00
---------------------------
转载自:https://juejin.cn/post/7169765223790805029