模式介绍
工厂模式
是一种创建型
设计模式,它提供了一个用于创建对象的接口,但允许子类决定实例化哪个类。工厂方法让一个类的实例化延迟到其子类。工厂模式是一种常见的设计模式,它提供了一种创建对象的接口,但具体创建的对象类型可以在运行时决定。工厂模式通常包括一个工厂类和多个产品类,工厂类负责创建产品类的实例。
工厂模式的优点包括:
分离了创建对象和使用的代码,使得代码更加灵活和可维护。
隐藏了对象创建的具体实现细节,让调用方与具体实现解耦。
可以通过扩展工厂类来增加新的产品类,而不需要修改调用方的代码。
工厂模式是一种灵活且可维护的设计模式,它通过将对象的创建和使用代码分离,隐藏了对象创建的具体实现细节,并且可以通过扩展工厂类来增加新的产品类。
模式类型
工厂模式可以分为简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂
-
简单工厂模式 :它属于工厂模式的一种,是一个创建对象的类,由这个类来封装实例化对象的行为(代码)。其实现了一个创建对象的类,由这个类来封装实例化对象的行为,它假定一个类族有相同的接口。简单工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
-
示例
以下是一个使用Java实现简单工厂模式的示例:
假设我们要创建一个简单的计算器,可以执行加、减、乘、除四种运算。我们可以使用简单工厂模式来实现这个计算器。
- 首先,定义一个接口
Operation
,表示一个运算操作:
java
public interface Operation {
double calculate(double num1, double num2);
}
- 接下来,为每种运算创建一个实现类,实现
Operation
接口:
java
public class Addition implements Operation {
@Override
public double calculate(double num1, double num2) {
return num1 + num2;
}
}
public class Subtraction implements Operation {
@Override
public double calculate(double num1, double num2) {
return num1 - num2;
}
}
public class Multiplication implements Operation {
@Override
public double calculate(double num1, double num2) {
return num1 * num2;
}
}
public class Division implements Operation {
@Override
public double calculate(double num1, double num2) {
if (num2 != 0) {
return num1 / num2;
} else {
throw new IllegalArgumentException("Division by zero is not allowed.");
}
}
}
- 创建一个工厂类
OperationFactory
,负责根据客户端的请求创建相应的运算实例:
java
public class OperationFactory {
public static Operation createOperation(char operator) {
switch (operator) {
case '+':
return new Addition();
case '-':
return new Subtraction();
case '*':
return new Multiplication();
case '/':
return new Division();
default:
throw new IllegalArgumentException("Invalid operator.");
}
}
}
- 最后,创建一个客户端类
Calculator
,通过工厂类获取运算实例,并执行计算:
java
public class Calculator {
public static void main(String[] args) {
double num1 = 10.0;
double num2 = 5.0;
char operator = '/'; // 可以修改为其他运算符:+、-、* 或 /
Operation operation = OperationFactory.createOperation(operator);
double result = operation.calculate(num1, num2);
System.out.println("Result: " + result);
}
}
这样,我们就使用简单工厂模式实现了一个简单的计算器。客户端只需指定运算符和操作数,工厂类负责创建相应的运算实例,并执行计算。这种方式使得代码更加灵活和可扩展,如果需要添加新的运算类型,只需创建新的实现类,并在工厂类中添加相应的创建逻辑即可。
工厂方法模式
-
工厂方法模式 :它定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
-
示例
工厂方法模式是一种创建型设计模式,它提供了一种创建对象的接口,但具体创建的对象类型可以在运行时决定。下面是一个简单的Java实现工厂方法模式的示例:
首先,我们定义一个公共的接口:
java
public interface Shape {
void draw();
}
然后,我们创建实现接口的具体类:
java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
接下来,我们创建一个抽象工厂类,该类声明了创建对象的接口:
java
public abstract class ShapeFactory {
public abstract Shape createShape(String shapeType);
}
然后,我们创建具体工厂类,这些类实现了抽象工厂类并返回具体类的对象:
java
public class RectangleFactory extends ShapeFactory {
@Override
public Shape createShape(String shapeType) {
if (shapeType != null) {
if (shapeType.equalsIgnoreCase("rectangle")) {
return new Rectangle();
} else {
return null;
}
} else {
return null;
}
}
}
public class CircleFactory extends ShapeFactory {
@Override
public Shape createShape(String shapeType) {
if (shapeType != null) {
if (shapeType.equalsIgnoreCase("circle")) {
return new Circle();
} else {
return null;
}
} else {
return null;
}
}
}
最后,我们在客户端代码中使用工厂对象来创建对象:
java
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory rectangleFactory = new RectangleFactory();
ShapeFactory circleFactory = new CircleFactory();
Shape rectangle = rectangleFactory.createShape("rectangle");
rectangle.draw();
Shape circle = circleFactory.createShape("circle");
circle.draw();
}
}
draw();
Shape circle = circleFactory.createShape("circle");
circle.draw();
}
}
抽象工厂模式
-
抽象工厂模式 :它定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。从设计层面看,抽象工厂模式就是对简单工厂模式的改进或称为进一步的抽象。
-
示例
抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。以下是一个使用Java实现的抽象工厂模式的示例:
首先,我们定义两个产品族:ProductA
和ProductB
。每个产品族都有两个具体产品:ConcreteProductA1
, ConcreteProductA2
, ConcreteProductB1
, ConcreteProductB2
。
java
public interface ProductA {
void operation1();
}
public interface ProductB {
void operation2();
}
public class ConcreteProductA1 implements ProductA {
@Override
public void operation1() {
System.out.println("ConcreteProductA1 operation1");
}
}
public class ConcreteProductA2 implements ProductA {
@Override
public void operation1() {
System.out.println("ConcreteProductA2 operation1");
}
}
public class ConcreteProductB1 implements ProductB {
@Override
public void operation2() {
System.out.println("ConcreteProductB1 operation2");
}
}
public class ConcreteProductB2 implements ProductB {
@Override
public void operation2() {
System.out.println("ConcreteProductB2 operation2");
}
}
接下来,我们定义抽象工厂接口AbstractFactory
,它声明了创建产品的方法。然后我们创建两个具体工厂ConcreteFactoryA
和ConcreteFactoryB
,它们实现了抽象工厂接口并分别创建ProductA
和ProductB
的实例。
java
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
public class ConcreteFactoryA implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteFactoryB implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
最后,我们在客户端代码中使用工厂对象来创建产品对象:
java
public class FactoryPatternDemo {
public static void main(String[] args) {
AbstractFactory factoryA = new ConcreteFactoryA();
AbstractFactory factoryB = new ConcreteFactoryB();
ProductA productA1 = factoryA.createProductA();
ProductA productA2 = factoryB.createProductA();
ProductB productB1 = factoryA.createProductB();
ProductB productB2 = factoryB.createProductB();
productA1.operation1();
}
}
主要特点
- 提供一个创建对象的接口,但子类决定要实例化哪个类。这意味着客户端只需要知道所创建对象的接口,而不必关心创建的具体实现。
- 创建过程在其子类执行。也就是说,工厂方法让子类决定实例化哪个类,而具体类的实例化过程是在子类中完成的。
- 隐藏复杂的逻辑处理过程。工厂模式通过将对象的创建和使用代码分离,让调用方与具体实现解耦,从而隐藏了对象创建的复杂逻辑。
- 增加新的产品时,只需要扩展一个工厂类。这意味着工厂模式具有良好的扩展性,可以通过扩展工厂类来增加新的产品类,而不需要修改调用方的代码。
- 屏蔽产品的具体实现,只关心产品的接口。这意味着调用方只需要关心所创建对象的接口,而不必关心具体实现,增加了代码的灵活性和可维护性。
工厂模式通过将对象的创建和使用代码分离,隐藏了对象创建的复杂逻辑,提供了良好的扩展性,并且屏蔽了产品的具体实现,只关心产品的接口。
应用场景
-
创建多个具有共同父类的子类对象,但具体创建哪个子类对象需要在运行时决定。
-
需要对一个类的实例化进行封装,并且调用方不需要知道具体是哪个子类的实例被创建。
-
需要提供一个通用的接口来创建对象,但具体创建哪个对象需要在运行时决定。
-
当一个对象的创建和使用是解耦的时候,即应用程序将对象的创建和初始化职责交给工厂对象,这也是工厂模式的常见应用场景。这样做的好处是,如果需求变更,需要将一个对象替换为另一个对象时,只需要修改创建该对象的工厂方法,而不需要修改所有使用该对象的代码。
-
当对象的创建过程比较复杂,或者在多个地方都需要使用时,通过将创建对象的代码统一放到工厂里面统一管理,可以减少代码的重复率,同时方便维护。
-
当一个类有很多子类,并且经常发生变化时,工厂模式可以将创建和使用分离,使用者不需要知道具体的创建过程,只需要使用即可。
工厂模式适用于需要创建多个具有共同父类的子类对象,但具体创建哪个子类对象需要在运行时决定的情况。同时,工厂模式也适用于需要对一个类的实例化进行封装,并且调用方不需要知道具体是哪个子类的实例被创建的情况。此外,当一个对象的创建和使用是解耦的时候,工厂模式也可以很好地应用。
代码示例
Java实现工厂模式
好的,下面是一个简单的Java工厂模式的实现:
java
public interface Product {
void use();
}
public class ConcreteProductA implements Product {
public void use() {
System.out.println("使用具体产品A");
}
}
public class ConcreteProductB implements Product {
public void use() {
System.out.println("使用具体产品B");
}
}
public class Factory {
public Product createProduct(String type) {
if (type.equals("A")) {
return new ConcreteProductA();
} else if (type.equals("B")) {
return new ConcreteProductB();
} else {
throw new IllegalArgumentException("无效的产品类型:" + type);
}
}
}
public class Client {
public static void main(String[] args) {
Factory factory = new Factory();
Product productA = factory.createProduct("A");
productA.use(); // 输出 "使用具体产品A"
Product productB = factory.createProduct("B");
productB.use(); // 输出 "使用具体产品B"
}
}
在这个例子中,我们定义了一个Product接口,它代表了所有的产品。然后我们创建了两个实现Product接口的具体产品ConcreteProductA和ConcreteProductB。接着我们创建了一个Factory类,它负责根据传入的参数来创建相应的具体产品。最后我们在Client类中通过Factory来创建具体的产品,并使用它们。
python实现工厂模式
好的,以下是一个Python实现的工厂模式的例子:
python
class Product(object):
def use(self):
raise NotImplementedError("子类必须实现use方法")
class ConcreteProductA(Product):
def use(self):
print("使用具体产品A")
class ConcreteProductB(Product):
def use(self):
print("使用具体产品B")
class Factory(object):
@staticmethod
def create_product(type):
if type == "A":
return ConcreteProductA()
elif type == "B":
return ConcreteProductB()
else:
raise ValueError("无效的产品类型:{}".format(type))
class Client(object):
def __init__(self):
self.product_a = Factory.create_product("A")
self.product_b = Factory.create_product("B")
def use_product_a(self):
self.product_a.use()
def use_product_b(self):
self.product_b.use()
if __name__ == "__main__":
client = Client()
client.use_product_a() # 输出 "使用具体产品A"
client.use_product_b() # 输出 "使用具体产品B"
在这个例子中,我们定义了一个抽象的Product类,它代表了所有的产品。然后我们创建了两个实现了Product类的具体产品ConcreteProductA和ConcreteProductB。接着我们创建了一个Factory类,它负责根据传入的参数来创建相应的具体产品。最后我们在Client类中通过Factory来创建具体的产品,并使用它们。
spring中的应用
工厂模式在Spring框架中得到了广泛应用。Spring框架的核心是IoC(控制反转)容器,它就是一个典型的工厂模式的应用。
IoC容器负责对象的创建、初始化、生命周期管理等,它就是一个工厂,将原本需要程序员自己创建和管理的对象交由IoC容器来负责。程序员只需要通过配置文件或者注解的方式来告诉IoC容器需要创建哪些对象,以及它们的依赖关系,IoC容器就会自动将这些对象创建好,并且根据依赖关系组装好。
另外,Spring框架中的AOP(面向切面编程)也用到了工厂模式。AOP是通过动态代理的方式来实现的,它需要在运行时创建一个代理对象,这个代理对象需要实现目标对象的接口,并且调用目标对象的方法。这个代理对象的创建过程就是通过工厂模式来实现的。
总之,工厂模式在Spring框架中扮演着非常重要的角色,它帮助我们简化了对象的创建和管理,提高了代码的可维护性和可重用性。