工厂模式能够将对象的创建和使用解耦,且当创建一个对象的过程繁杂时,又有大量地方需要重复创建该对象,使用工厂模式则可以降低代码的重复率。另外,将对象的创建封装到工厂类,当创建过程发生改变时,可直接修改工厂类,而无需到每个创建对象的地方修改代码,降低了系统的维护成本。
目录
一、简单工厂模式
1.定义
又称静态工厂模式,该模式定义一个专门的类负责实例的创建,被创建的实例通常有相同的父类。
2.角色:
- Factory:工厂类,根据参数的不同创建不同的实例
- Product:抽象产品类
- ConcreteProduct:具体产品类
3.特点
- 优点:将对象的创建和对象本身业务处理分离,降低系统耦合度。
- 缺点:因为对象的创建交由工厂处理,当产品种类过多时,需要修改工厂方法,不符合开闭原则,且将使得工厂方法逻辑复杂,不易于维护和扩展。
4.示例
产品接口:
public interface Product {
void say();
}
具体产品类:
// ConcreteProductA
public class ConcreteProductA implements Product {
@Override
public void say() {
System.out.println("I'm Product A.");
}
}
// ConcreteProductB
public class ConcreteProductB implements Product {
@Override
public void say() {
System.out.println("I'm Product B.");
}
}
工厂类:
public class Factory {
public static Product createProduct(String arg) {
if (arg == "A")
return new ConcreteProductA();
else if (arg == "B")
return new ConcreteProductB();
return null;
}
}
测试类:
public class TestSimpleFactory {
public static void main(String[] args) {
Product productA = Factory.createProduct("A");
Product productB = Factory.createProduct("B");
productA.say();
productB.say();
}
}
// 输出
// I'm Product A.
// I'm Product B.
二、工厂方法模式
1.定义
定义了一个创建对象的接口,但由子类决定要实例化的对象是哪一个,该模式让类把实例化推迟到子类。
2.角色
- Product:抽象产品类
- ConcreteProduct:具体产品类
- Factory:抽象工厂类
- ConcreteFactory:具体工厂类
3.特点
- 优点:实例的创建延迟到子类执行,由子类来确定创建何种实例,当有新产品加入时,只需要添加一个新工厂和新产品而无需修改现有系统。
- 缺点:因为产品和工厂是成对增加,一定程度上增加了系统的复杂度。
4.示例
产品接口及具体产品类同上
工厂接口:
public interface Factory {
Product createProduct();
}
具体工厂接口:
// ConcreteFactoryA
public class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// ConcreteFactoryB
public class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
测试类:
public class TestFactoryMethod {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Factory factoryB = new ConcreteFactoryB();
Product productA = factoryA.createProduct();
Product productB = factoryB.createProduct();
productA.say();
productB.say();
}
}
// 输出
// I'm Product A.
// I'm Product B.
三、抽象工厂类
1.定义
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
2.角色
- AbstractProduct:抽象产品类
- ConcreteProduct:具体产品类
- AbstractFactory:抽象工厂类
- ConcreteFactory:具体工厂类
3.特点
- 优点:可通过具体工厂类创建产品族的多个对象。
- 缺点:其开闭原则具有倾斜性,即增加或者修改产品族比较方便,可直接增加新的具体工厂和产品族,但增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类。
4.示例
产品接口及其具体产品类:
// AbstractProductA
public interface AbstractProductA {
void use();
}
// AbstractProductB
public interface AbstractProductB {
void eat();
}
// ProductA1
public class ProductA1 implements AbstractProductA {
@Override
public void use() {
System.out.println("I'm using ProductA1.");
}
}
// ProductA2
public class ProductA2 implements AbstractProductA {
@Override
public void use() {
System.out.println("I'm using ProductA2.");
}
}
// ProductB1
public class ProductB1 implements AbstractProductB {
@Override
public void eat() {
System.out.println("I'm eating ProductB1.");
}
}
// ProductB2
public class ProductB2 implements AbstractProductB {
@Override
public void eat() {
System.out.println("I'm eating ProductB2.");
}
}
工厂接口及其具体工厂类:
// Factory
public interface Factory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// ConcreteFactory1
public class ConcreteFactory1 implements Factory {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
// ConcreteFactory2
public class ConcreteFactory2 implements Factory {
@Override
public AbstractProductA createProductA() {
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ProductB2();
}
}
测试类:
public class TestAbstractFactory {
public static void main(String[] args) {
Factory factory1 = new ConcreteFactory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productA1.use();
productB1.eat();
Factory factory2 = new ConcreteFactory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productA2.use();
productB2.eat();
}
}
// 输出
// I'm using ProductA1.
// I'm eating ProductB1.
// I'm using ProductA2.
// I'm eating ProductB2.
参考:
1.《Head First 设计模式》
2.图说设计模式 https://design-patterns.readthedocs.io/zh_CN/latest/index.html