学习理解Java工厂模式
- 一、前言
- 二、简单工程模式
- 三、工厂方法模式
- 四、抽象工厂模式
- 五、静态工厂模式和 new 有什么区别?
- 六、总结
一、前言
工厂模式目的是封装对象的创建过程,将对象的创建和使用分离开来,从而提高代码的可维护性和可扩展性。下面是它们之间的区别:
- 简单工厂模式:简单工厂模式是最简单的工厂模式,它将对象的创建过程封装在一个工厂类中,客户端通过工厂类来创建对象。简单工厂模式通常只有一个工厂类和多个产品类,客户端不需要关心具体的产品类,只需要知道它们的名称或类型即可。
- 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换,符合开闭原则。
- 抽象工厂模式:抽象工厂模式是工厂方法模式的升级版,它定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换,符合开闭原则。
二、简单工程模式
简单工厂模式可以很好地隐藏对象创建的细节,使得客户端代码不必关心具体对象的创建过程。但是简单工厂模式也有缺点,例如当需要添加新的产品类时,就必须修改工厂类的代码,这违反了开闭原则。
public class AnimalFactory {public static Animal createAnimal(String type) {if (type.equals("Dog")) {return new Dog();} else if (type.equals("Cat")) {return new Cat();} else {throw new IllegalArgumentException("Invalid animal type: " + type);}}
}public interface Animal {void speak();
}public class Dog implements Animal {@Overridepublic void speak() {System.out.println("Woof!");}
}public class Cat implements Animal {@Overridepublic void speak() {System.out.println("Meow!");}
}public class Client {public static void main(String[] args) {Animal dog = AnimalFactory.createAnimal("Dog");Animal cat = AnimalFactory.createAnimal("Cat");Animal pig = AnimalFactory.createAnimal("pig");dog.speak(); // Output: Woof!cat.speak(); // Output: Meow!pig.speak(); // Output: Invalid animal type: pig}
}
三、工厂方法模式
工厂方法模式通常通过一个抽象工厂接口和多个具体工厂实现类来实现。
- 抽象工厂接口(Factory):定义了工厂方法的接口,声明了用于创建对象的方法,这些方法可以返回一个抽象产品类型或者一个具体产品类型。
- 具体工厂实现类(Concrete Factory):实现了抽象工厂接口中定义的方法,具体负责创建一组产品对象。
- 抽象产品接口(Product):定义了产品对象的通用接口,描述了产品对象的属性和方法。
- 具体产品实现类(Concrete Product):实现了抽象产品接口中定义的方法,是被工厂方法创建的对象。
// 抽象产品接口
interface Car {void run();
}// 具体产品实现类1
class Benz implements Car {@Overridepublic void run() {System.out.println("Benz is running.");}
}// 具体产品实现类2
class BMW implements Car {@Overridepublic void run() {System.out.println("BMW is running.");}
}// 抽象工厂接口
interface CarFactory {Car createCar();
}// 具体工厂实现类1
class BenzFactory implements CarFactory {@Overridepublic Car createCar() {return new Benz();}
}// 具体工厂实现类2
class BMWFactory implements CarFactory {@Overridepublic Car createCar() {return new BMW();}
}// 客户端代码
public class Client {public static void main(String[] args) {// 创建奔驰车CarFactory benzFactory = new BenzFactory();Car benzCar = benzFactory.createCar();benzCar.run();// 创建宝马车CarFactory bmwFactory = new BMWFactory();Car bmwCar = bmwFactory.createCar();bmwCar.run();}
}
四、抽象工厂模式
抽象工厂模式的核心思想是“工厂的工厂”。这意味着,不同的工厂可以创建不同的对象家族,而不是单个对象。这些工厂可以是具体的类,也可以是抽象类或接口。客户端使用这些工厂接口创建对象,而无需知道底层的实现细节。
// 定义抽象工厂接口
interface AbstractFactory {public ProductA createProductA();public ProductB createProductB();
}// 定义具体工厂类
class ConcreteFactory1 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA1();}public ProductB createProductB() {return new ConcreteProductB1();}
}class ConcreteFactory2 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA2();}public ProductB createProductB() {return new ConcreteProductB2();}
}// 定义产品接口
interface ProductA {public String getDescription();
}interface ProductB {public String getDescription();
}// 定义具体产品类
class ConcreteProductA1 implements ProductA {public String getDescription() {return "Product A1";}
}class ConcreteProductA2 implements ProductA {public String getDescription() {return "Product A2";}
}class ConcreteProductB1 implements ProductB {public String getDescription() {return "Product B1";}
}class ConcreteProductB2 implements ProductB {public String getDescription() {return "Product B2";}
}// 使用抽象工厂创建产品
public class Client {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();}
}
在这个例子中,AbstractFactory
接口定义了两个方法 createProductA
和 createProductB
,用于创建产品 A 和产品 B。具体工厂类 ConcreteFactory1
和 ConcreteFactory2
分别实现了这个接口,每个工厂都可以创建自己的一组产品。产品由 ProductA
和 ProductB
接口定义,而具体的产品类 ConcreteProductA1
,ConcreteProductA2
,ConcreteProductB1
和 ConcreteProductB2
实现了这些接口。
五、静态工厂模式和 new 有什么区别?
在Java中,使用new关键字创建对象是主动获取资源的方式,应用与资源之间是直接依赖的。而采用工厂模式获取对象时,是应用向工厂要对象,工厂从容器中获取对象返回给应用,是被动的,从而降低了应用和资源之间的依赖关系。这种主动权的变化就叫控制反转。
静态工厂方法可以通过方法名字来表示创建了什么对象,比如下面这个方法,就表示创建一个可能是素数的BigInteger,所以,你可以通过名字来表明对象的作用。
总之,静态工厂模式和new创建对象有很大的区别。静态工厂模式可以降低应用和资源之间的依赖关系,使得代码更加灵活、可维护性更高;而new创建对象则是主动获取资源的方式。
六、总结
- 创建对象的方式不同:
- 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换。
- 抽象工厂模式:抽象工厂模式定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换。
- 创建的对象类型不同:
- 工厂方法模式:工厂方法模式适用于创建多种类型的产品对象。
- 抽象工厂模式:抽象工厂模式适用于创建多个产品族的对象。
- 代码结构不同:
-
工厂方法模式:工厂方法模式通常只需要一个工厂接口和多个具体工厂类,客户端只需要调用工厂接口的方法即可创建对象。
抽象工厂模式:抽象工厂模式需要定义多个工厂接口和产品族接口,每个工厂接口和产品族接口都需要对应多个具体实现类,代码结构更加复杂。 -
简单工厂模式适用于创建单一类型的产品对象,工厂方法模式适用于创建多种类型的产品对象,而抽象工厂模式适用于创建多个产品族的对象。