目录
设计模式(分类) 设计模式(六大原则)
创建型
工厂方法 抽象工厂模式 单例模式 建造者模式
设计模式中的工厂方法(Factory Method)是一种创建型模式,它提供了一种创建对象的灵活方式,通过将对象的创建过程封装在子类中来实现对象的创建延迟。工厂方法模式的核心在于定义一个用于创建对象的接口(或抽象类),并允许子类决定实例化哪个类的对象。以下是对工厂方法模式的详细说明:
模式结构
工厂方法模式通常包含以下角色:
-
抽象产品(Product):定义了一个产品的接口,是所有具体产品类的公共父类或接口,声明了产品的通用行为。
-
具体产品(Concrete Product):实现了抽象产品的接口,是工厂方法所创建的对象的具体类型。可以有多个具体产品类,每个类对应一种具体产品。
-
抽象工厂(Creator):定义了一个创建产品对象的接口,声明了一个创建产品的工厂方法。该方法通常返回抽象产品类型,以便调用者可以使用统一的方式处理各种具体产品。
-
具体工厂(Concrete Creator):实现了抽象工厂接口,提供了创建具体产品对象的实现。每一个具体工厂类对应一种具体产品类型,通过重写工厂方法来创建对应的具体产品对象。
工作原理
- 客户端:需要创建对象时,不直接实例化具体产品类,而是通过调用具体工厂类的工厂方法来获取产品对象。
- 具体工厂:负责实现工厂方法,该方法根据具体工厂的类型返回相应具体产品类型的实例。具体工厂隐藏了创建产品的具体细节,客户端只需关心所需产品的类型,无需了解创建过程。
- 抽象产品:作为产品对象的通用接口,为客户端提供统一的操作入口,使得客户端可以使用抽象产品类型的引用来处理具体产品对象,无需关心实际使用的是哪种具体产品。
优缺点
优点
- 封装性:将对象的创建过程封装在工厂类中,客户端无需关心对象的具体创建过程,只需知道所需产品的类型即可。
- 灵活性:通过增加新的具体工厂和具体产品类,可以很容易地扩展系统以支持新的产品类型,符合“开闭原则”。
- 解耦:客户端与具体产品类解耦,只需要和抽象产品以及具体工厂打交道,降低了系统的耦合度。
- 代码结构清晰:通过工厂方法模式,可以将产品类的实例化代码集中在一起,使得代码结构更加清晰,易于维护。
缺点
- 类的层级结构增加:引入了额外的抽象层和具体工厂类,可能导致类的层级结构变得复杂。
- 增加系统的理解与设计难度:对于不熟悉工厂方法模式的开发者,可能需要花费更多时间理解系统的设计和实现。
- 每次新增产品时都需要添加新的具体工厂:如果产品种类繁多,可能会导致具体工厂类数量的增长。
适用场景
- 对象创建过程比较复杂:当创建对象涉及大量初始化工作,或者需要依赖具体环境、条件来确定创建何种对象时,工厂方法模式可以将这些复杂性封装在工厂类中。
- 系统需要支持多种产品类型:如果有多种不同类型的产品需要创建,并且希望在不修改客户端代码的情况下引入新产品,工厂方法模式可以很好地适应这种需求。
- 隔离直接创建对象的责任:如果不想让客户端直接接触对象创建的细节,或者需要将对象的创建过程与使用过程分离,可以使用工厂方法模式。
代码示例(以Java为例)
// 抽象产品
public interface Car {void drive();
}// 具体产品A
public class SportsCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sports car.");}
}// 具体产品B
public class SedanCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan car.");}
}// 抽象工厂
public abstract class CarFactory {public abstract Car createCar();
}// 具体工厂A
public class SportsCarFactory extends CarFactory {@Overridepublic Car createCar() {return new SportsCar();}
}// 具体工厂B
public class SedanCarFactory extends CarFactory {@Overridepublic Car createCar() {return new SedanCar();}
}// 客户端代码
public class Client {public static void main(String[] args) {CarFactory factory = new SportsCarFactory(); // 或者 new SedanCarFactory()Car car = factory.createCar();car.drive();}
}//在这个例子中,客户端通过调用具体工厂(如SportsCarFactory或SedanCarFactory)的createCar()方法来获取所需的Car对象。
//具体创建哪种类型的Car对象由具体工厂决定,客户端无需知道具体的创建细节,只需与Car接口和工厂类交互。这样,系统在不修改现有代码的情况下就能轻易地添加新的汽车类型和对应的工厂类,实现了良好的扩展性
代码示例(以Python为例)
在这个Python示例中:
Animal
类作为抽象产品,定义了动物的基本属性(如name
)和抽象方法make_sound()
,要求子类必须实现该方法。Dog
和Cat
类是具体产品,它们继承自Animal
类并实现了各自的make_sound()
方法,分别模拟狗和猫发出的声音。AnimalFactory
类作为抽象工厂,定义了一个静态方法create_animal()
,该方法接收动物类型和名字作为参数,根据传入的动物类型创建相应的具体动物对象。这里使用静态方法简化了示例,实际应用中也可以定义为普通方法并创建AnimalFactory
的实例来调用。- 客户端代码中,创建了
AnimalFactory
实例,并通过调用其create_animal()
方法创建了Dog
和Cat
对象。客户端无需知道如何直接创建这些对象,只需与AnimalFactory
交互并传递所需动物的类型和名称即可。
这个例子展示了工厂方法模式在Python中的应用,通过工厂方法创建对象,客户端代码与具体的动物创建逻辑解耦,增加了系统的灵活性和可扩展性。如果需要添加新的动物类型(如兔子),只需定义新的动物类并更新工厂方法中的逻辑即可,无需改动客户端代码。
# 抽象产品
class Animal:def __init__(self, name):self.name = namedef make_sound(self):raise NotImplementedError("Subclasses must implement this abstract method")def __str__(self):return f"{self.name} makes {self.make_sound()} sound"# 具体产品
class Dog(Animal):def make_sound(self):return "Woof!"class Cat(Animal):def make_sound(self):return "Meow!"# 抽象工厂
class AnimalFactory:@staticmethoddef create_animal(animal_type, name):if animal_type == "dog":return Dog(name)elif animal_type == "cat":return Cat(name)else:raise ValueError(f"Unsupported animal type: {animal_type}")# 客户端代码
def main():animal_factory = AnimalFactory()dog = animal_factory.create_animal("dog", "Rex")print(dog)cat = animal_factory.create_animal("cat", "Whiskers")print(cat)if __name__ == "__main__":main()