在软件设计中,工厂模式是一种常见的设计模式,它提供了一种创建对象的最佳方式。通过工厂模式,我们可以将对象的创建逻辑与使用逻辑分离,降低代码的耦合度,提高系统的可扩展性和可维护性。
Java中的工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式是最简单的工厂模式,它通过一个专门的类来负责创建其他类的实例,而不需要明确指定具体将要创建的类。这个专门的类称为“简单工厂类”或“工厂类”。
在Java中,简单工厂模式是一种创建型设计模式,它由一个单独的类(称为工厂类)负责创建其他类的实例,而无需将这些类的实例化逻辑暴露给客户端。
简单工厂模式通常用于创建具有共同父类或接口的对象的场景。
下面是一个简单工厂模式的Java实现示例:
首先,定义一个产品接口或抽象类:
// 产品接口
public interface Product {
void use();
}
然后,实现具体产品类:
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用具体产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用具体产品B");
}
}
接下来,创建简单工厂类:
// 简单工厂类
public class SimpleFactory {
// 静态工厂方法,用于创建产品
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ConcreteProductA();
} else if ("B".equals(type)) {
return new ConcreteProductB();
} else {
throw new IllegalArgumentException("不支持的产品类型: " + type);
}
}
}
最后,客户端代码可以这样使用简单工厂:
public class Client {
public static void main(String[] args) {
// 通过简单工厂创建产品A
Product productA = SimpleFactory.createProduct("A");
productA.use(); // 输出:使用具体产品A
// 通过简单工厂创建产品B
Product productB = SimpleFactory.createProduct("B");
productB.use(); // 输出:使用具体产品B
// 尝试创建不存在的产品类型将抛出异常
// Product productC = SimpleFactory.createProduct("C");
}
}
SimpleFactory
类包含一个静态方法createProduct
,它根据传入的类型字符串创建并返回相应的产品实例。客户端代码通过调用这个静态工厂方法来获取产品实例,而无需直接与具体的产品类交互。
在实际应用中,如果需要频繁添加新的产品类型,可能会更倾向于使用抽象工厂模式或其他更灵活的工厂模式。
工厂方法模式是对简单工厂模式的进一步抽象化。它将对象的创建延迟到子类中进行,从而实现了更好的扩展性。在工厂方法模式中,抽象工厂类负责定义创建产品对象的接口,而具体工厂类则负责实现具体的产品创建逻辑。
下面是一个工厂方法模式的Java实现示例:
首先,定义一个产品接口:
// 产品接口
public interface Product {
void use();
}
然后,实现具体产品类:
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用具体产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用具体产品B");
}
}
接下来,创建抽象工厂类,并定义工厂方法:
// 抽象工厂类
public abstract class Creator {
// 工厂方法,声明为抽象方法,由子类实现
public abstract Product factoryMethod();
// 一个通用的方法,使用工厂方法来创建产品
public final Product createProduct() {
Product product = factoryMethod();
// 这里可以添加一些额外的逻辑,比如初始化产品等
return product;
}
}
然后,实现具体的工厂子类:
// 具体工厂子类A,用于创建ConcreteProductA
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
// 具体工厂子类B,用于创建ConcreteProductB
public class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
最后,客户端代码可以这样使用工厂方法模式:
public class Client {
public static void main(String[] args) {
// 使用具体工厂子类A来创建产品A
Creator creatorA = new ConcreteCreatorA();
Product productA = creatorA.createProduct();
productA.use(); // 输出:使用具体产品A
// 使用具体工厂子类B来创建产品B
Creator creatorB = new ConcreteCreatorB();
Product productB = creatorB.createProduct();
productB.use(); // 输出:使用具体产品B
}
}
例子中,Creator
是一个抽象工厂类,它声明了一个抽象方法factoryMethod()
,这个方法由具体的工厂子类(ConcreteCreatorA
和ConcreteCreatorB
)来实现。客户端代码通过创建具体工厂类的实例并调用createProduct()
方法来创建产品。每个具体工厂类都知道如何创建和返回一种具体的产品。
抽象工厂模式是对工厂方法模式的进一步抽象化。它提供了一组用于创建一系列相关或互相依赖对象的接口,而不需要指定它们具体的类。在抽象工厂模式中,抽象工厂类负责定义创建产品家族的接口,而具体工厂类则负责实现具体的产品家族创建逻辑。产品家族是指位于不同产品等级结构中,功能相关联的产品组成的家族。
以下是Java中实现抽象工厂模式的一种方式:
首先,定义产品接口:
// 产品A的接口
public interface ProductA {
void use();
}
// 产品B的接口
public interface ProductB {
void use();
}
然后,实现具体产品:
// 具体产品A1
public class ConcreteProductA1 implements ProductA {
@Override
public void use() {
System.out.println("使用具体产品A1");
}
}
// 具体产品A2
public class ConcreteProductA2 implements ProductA {
@Override
public void use() {
System.out.println("使用具体产品A2");
}
}
// 具体产品B1
public class ConcreteProductB1 implements ProductB {
@Override
public void use() {
System.out.println("使用具体产品B1");
}
}
// 具体产品B2
public class ConcreteProductB2 implements ProductB {
@Override
public void use() {
System.out.println("使用具体产品B2");
}
}
接下来,定义抽象工厂接口:
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
然后,实现具体工厂:
// 具体工厂1,负责创建产品A1和产品B1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2,负责创建产品A2和产品B2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
最后,客户端代码可以这样使用抽象工厂:
public class Client {
public static void main(String[] args) {
// 使用具体工厂1来创建产品
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.use(); // 输出:使用具体产品A1
productB1.use(); // 输出:使用具体产品B1
// 使用具体工厂2来创建产品
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.use(); // 输出:使用具体产品A2
productB2.use(); // 输出:使用具体产品B2
}
}
例子中,AbstractFactory
接口定义了两个创建产品的方法,createProductA()
和createProductB()
。ConcreteFactory1
和ConcreteFactory2
分别实现了这些方法以创建不同的具体产品。客户端代码通过具体的工厂来创建和使用产品,而不需要直接与具体产品类打交道。这种方式提供了更好的灵活性和可扩展性,因为你可以在不修改客户端代码的情况下增加新的工厂和产品。
在实际开发中,抽象工厂模式的实现可能更加复杂和庞大。为了保持代码的清晰和可维护性,我们需要合理地划分产品等级结构和产品家族,并遵循单一职责原则和开闭原则进行设计。同时,在实际应用中,我们可以根据具体需求选择使用简单工厂模式、工厂方法模式或抽象工厂模式中的任意一种或多种组合使用以满足需求。例如,在某些情况下,我们可以将简单工厂模式与工厂方法模式结合使用以简化代码结构并提高灵活性;而在其他情况下,我们可能需要使用抽象工厂模式来处理更复杂的对象创建场景。
术因分享而日新,每获新知,喜溢心扉。 诚邀关注公众号 『
码到三十五
』 ,获取更多技术资料。