简单工厂模式
使用简单工厂模式的优点包括:
简单工厂的优点
- 它提供了一种创建对象的方法,而无需指定将要创建的对象的确切类。这在事先不知道要创建的特定对象类型或可能发生变化的情况下很有用。
- 它为创建对象提供了单一的控制点。这可以更轻松地管理和维护代码库,因为所有对象创建都是通过工厂处理的。
- 它促进了对象之间的松散耦合。工厂创建对象时不需要知道它们是如何实现的具体细节,这使得代码具有更大的灵活性和可重用性。
潜在缺点
- 它可以使代码库更加复杂。工厂的使用增加了一个额外的抽象层,这会使代码更难理解和维护。
- 它可能违反单一职责原则。工厂负责创建对象,这是一个独立于它创建的类的其他职责的关注点。这会使理解类和工厂之间的关系变得困难。
- 它会使单元测试更加困难。由于工厂创建对象时未指定其确切类型,因此编写单元测试以充分涵盖可由工厂创建的所有可能对象类型可能具有挑战性。
代码模拟
public class Dog {
private String name;
public Dog(String name) {
this.name = name;
}
public String speak() {
return "Woof!";
}
}
public class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
public String speak() {
return "Meow!";
}
}
public class Parrot {
private String name;
public Parrot(String name) {
this.name = name;
}
public String speak() {
return "Squawk!";
}
}
public class PetFactory {
public static Pet getPet(String petType, String name) {
if (petType.equalsIgnoreCase("dog")) {
return new Dog(name);
} else if (petType.equalsIgnoreCase("cat")) {
return new Cat(name);
} else if (petType.equalsIgnoreCase("parrot")) {
return new Parrot(name);
}
return null;
}
}
public class Main {
public static void main(String[] args) {
PetFactory petFactory = new PetFactory();
Pet pet = petFactory.getPet("dog", "Max");
System.out.println(pet.speak());
pet = petFactory.getPet("cat", "Fluffy");
System.out.println(pet.speak());
pet = petFactory.getPet("parrot", "Polly");
System.out.println(pet.speak());
}
}
在此示例中,PetFactory该类有一个getPet()将 apetType和 aname作为输入参数的方法。该方法使用petType来确定要创建哪种类型的宠物对象并返回相应类的实例。该类PetFactory可用于创建、 和类的实例Dog,而无需指定将创建的确切类。Cat Parrot
工厂模式
工厂模式和简单工厂模式的区别与提升
工厂模型在几个方面是对简单工厂模型的改进。一方面,它允许在不指定将要创建的对象的确切类的情况下创建对象。这在事先不知道要创建的对象的确切类型的情况下,或者在根据输入数据决定创建对象类型的情况下很有用。
此外,工厂模型在使用对象的代码和创建对象的代码之间提供了一定程度的抽象。这可以使维护和修改代码变得更加容易,并使其更加灵活和可重用。
此外,工厂模型可以更轻松地实现新类型的对象,而无需更改现有代码。这可以让代码库更容易扩展和演进。
示例代码
// 形状接口
public interface Shape {
// 绘制形状
void draw();
}
// 圆形类,实现 Shape 接口
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("在 Circle 类的 draw 方法内部。");
}
}
// 矩形类,实现 Shape 接口
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("在 Rectangle 类的 draw 方法内部。");
}
}
// 形状工厂类
public class ShapeFactory {
// 使用 getShape 方法来获取形状类型的对象
public Shape getShape(String shapeType) {
if(shapeType == null) {
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
// 工厂模式示例
public class FactoryPatternDemo {
public static void main(String[] args) {
// 获取形状工厂
ShapeFactory shapeFactory = new ShapeFactory();
// 获取 Circle 对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
// 调用 Circle 的 draw 方法
shape1.draw();
// 获取 Rectangle 对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
// 调用 Rectangle 的 draw 方法
shape2.draw();
}
}
在上面的代码中,我们定义了一个 Shape 接口和两个实现了这个接口的类,Circle 和 Rectangle,用于创建不同形状的对象。我们还定义了一个 ShapeFactory 类,用于根据用户提供的形状类
代码解释
上面的代码演示了如何使用工厂模式来创建不同形状的对象。具体来说,它定义了一个 Shape 接口,表示形状,并定义了一个 draw 方法用于绘制形状。然后定义了两个实现了 Shape 接口的类,Circle 和 Rectangle,分别表示圆形和矩形。
接着,定义了一个 ShapeFactory 类,它包含一个 getShape 方法,用于根据用户提供的形状类型(例如 "CIRCLE" 或 "RECTANGLE")来创建相应的形状对象。最后,在 main 方法中,我们创建了一个 ShapeFactory 对象,然后调用它的 getShape 方法来创建 Circle 和 Rectangle 对象,并调用它们的 draw 方法来绘制这两个形状。
通过使用工厂模式,我们可以将对象的创建和使用分离开来,使得代码更容易维护和扩展。例如,如果我们想要添加新的形状,只需要实现 Shape 接口,并在 ShapeFactory 类的 getShape 方法中添加一个分支来处理新的形状类型即可。这样,就可以避免对现有代码的修改,提高代码的灵活性和可扩展性。
抽象工厂模式
抽象工厂模式是一种设计模式,它提供了一种方法来创建相互依赖的对象,而无需指定它们具体的类。它通过将相关的对象的创建集中在一个工厂中,从而使得代码更容易维护和扩展。
抽象工厂模式是一种创建型设计模式,它提供了一种方法来创建一组相关或相互依赖的对象,无需指定他们的具体类。
下面是一个典型的抽象工厂模式模板,其中包含了抽象工厂类、具体工厂类、抽象产品类、具体产品类:
/**
* 抽象工厂类
*/
public abstract class AbstractFactory {
/**
* 创建产品A
*/
public abstract ProductA createProductA();
/**
* 创建产品B
*/
public abstract ProductB createProductB();
}
/**
* 具体工厂类
*/
public class ConcreteFactory extends AbstractFactory {
/**
* 创建产品A
*/
public ProductA createProductA() {
return new ConcreteProductA();
}
/**
* 创建产品B
*/
public ProductB createProductB() {
return new ConcreteProductB();
}
}
/**
* 抽象产品类
*/
public abstract class ProductA {
// 产品共有方法
public void sharedMethod() {
// ...
}
// 抽象方法
public abstract void doSomething();
}
/**
* 具体产品类
*/
public class ConcreteProductA extends ProductA {
// 实现抽象方法
public void doSomething() {
// ...
}
}
/**
* 抽象产品类
*/
public abstract class ProductB {
// 产品共有方法
public void sharedMethod() {
// ...
}
// 抽象方法
public abstract void doSomething();
}
/**
* 具体产品类
*/
public class ConcreteProductB extends ProductB {
// 实现抽象方法
public void doSomething() {
// ...
}
}
上述代码解读
上述代码定义了用于创建产品的抽象工厂模式。抽象工厂类AbstractFactory定义了两个抽象方法来创建类型ProductA和的产品ProductB。这些方法由ConcreteFactory类实现,类分别扩展AbstractFactory和创建 和 的ConcreteProductA实例ConcreteProductB。
ProductA并且ProductB是抽象类,它们定义了一个通用方法sharedMethod和一个抽象方法 ,doSomething它们必须由具体的产品类来实现。在此代码中,ConcreteProductA和分别是和类ConcreteProductB的具体实现。他们都实现了这个方法。ProductA``ProductB``doSomething
要使用这种抽象工厂模式,客户可以创建一个实例ConcreteFactory并使用它来创建实例,ProductA而ProductB无需知道这些产品的具体实现细节。这允许客户端与产品实现解耦,从而更容易在未来添加新类型的产品。
优缺点
抽象工厂模式的优点:
- 将具体的创建逻辑封装在具体工厂中,对于客户端来说是透明的,客户端无需关心具体产品是如何创建的。
- 可以很容易地增加新的具体工厂和具体产品,满足开闭原则。
- 客户端与具体产品的耦合度降低,可以轻松地替换具体产品。
缺点:
- 抽象工厂类需要针对每一种具体产品都进行扩展,增加系统的复杂度。
- 当需要更换具体工厂时,需要修改客户端代码,不满足开闭原则。
需要注意,抽象工厂模式不同于工厂方法模式,工厂方法模式只有一个抽象工厂类和多个具体工厂类,每个具体工厂类只能创建一种具体产品。而抽象工厂模式有多个抽象工厂类和多个具体工厂类,每个抽象工厂类可以创建多种不同的具体产品。
抽象工厂模式适用于创建一组相关或相互依赖的产品对象,且客户端无需关心具体产品对象的创建过程。例如,一个电商网站提供了多种不同的支付方式,如支付宝、微信支付等,可以使用抽象工厂模式来创建不同支付方式对应的产品对象,客户端可以根据需要选择不同的支付方式,无需关心支付方式的具体实现细节。
总结
常见的工厂模式有三种:简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式:
- 简单工厂模式由一个工厂类来负责所有产品的创建。
- 客户端需要通过工厂类提供的静态方法来创建产品,无需关心产品的创建过程。
- 简单工厂模式实现简单,易于理解和使用,但不满足开闭原则,一旦添加新的产品需要修改工厂类的代码。
工厂方法模式:
- 工厂方法模式由抽象工厂类和多个具体工厂类组成。
- 抽象工厂类定义了产品的创建方法,而具体工厂类则实现了创建具体产品的方法。
- 客户端通过指定具体工厂类来创建产品,工厂方法模式能够让客户端与具体产品的实现解耦,满足开闭原则。
- 工厂方法模式的缺点是增加新的产品需要修改抽象工厂类及所有的具体工厂类,会增加系统的复杂度。
抽象工厂模式:
- 抽象工厂模式由多个抽象工厂类和多个具体工厂类组成。
- 抽象工厂类定义了多种产品的创建方法,而具体工厂类则实现了创建不同类型产品的方法。
- 客户端通过指定具体工厂类来创建产品,抽象工厂模式能够让客户端与具体产品的实现解耦,满足开闭原则。
- 抽象工厂模式的优点是可以很容易地增加新的产品,但缺点是抽象工厂类需要针对每一种具体产品都进行扩展,增加系统的复杂度。
总结来说,简单工厂模式实现简单,但不满足开闭原则;工厂方法模式满足开闭原则,但增加新产品需要修改抽象工厂类及所有的具体工厂类;抽象工厂模式能很容易地增加新产品,但需要针对每一种具体产品都进行扩展,增加系统的复杂度。应用时需要根据实际情况选择合适的工厂模式。
补充
什么时候可以考虑使用工厂模式
当满足以下条件时,可以考虑使用工厂模式:
- 系统需要创建不同类型的对象,但具体要创建的对象类型在编译时是未知的。
- 对象的创建涉及一组复杂的步骤,例如初始化对象、设置其属性和执行其他操作。
- 客户端代码需要与正在创建的对象的实现细节分离。
- 系统需要能够在不修改现有代码的情况下轻松添加新类型的对象。
一般来说,工厂模式可以帮助降低对象创建的复杂性,并提供一种灵活的方式来管理系统中不同组件之间的依赖关系。
怎么去选择不同工厂模式
- 产品创建过程的复杂性:如果产品创建过程很简单,只涉及几个步骤,一个简单的工厂模式可能就足够了。如果产品创建过程复杂且涉及多个步骤,工厂方法或抽象工厂模式可能更合适。
- 产品数量:如果只有一种产品,简单的工厂模式可能就足够了。如果有多种类型的产品,工厂方法或抽象工厂模式可能更合适。
- 可扩展性的需求:如果系统需要能够方便地添加新产品,抽象工厂模式可能是最好的选择。
- 客户端与产品之间的耦合程度:如果客户端需要与产品紧密耦合,一个简单的工厂模式可能就足够了。如果客户端需要与产品松散耦合,工厂方法或抽象工厂模式可能更合适。
最终,工厂模式的选择取决于系统的具体要求和不同因素之间的权衡。
本文正在参加「金石计划 . 瓜分6万现金大奖」