java设计模式二、工厂
概述
工厂方法模式是一种常用的创建型设计模式,它通过将对象的创建过程封装在工厂类中,实现了创建与使用的分离。这种模式不仅提高了代码的复用性,还增强了系统的灵活性和可扩展性。本文将详细介绍工厂方法模式的三种形式:简单工厂模式、工厂方法模式和抽象工厂模式,并通过Java代码示例帮助你深入理解。
什么是工厂方法模式
工厂方法模式(Factory Method Pattern)由父类提供一个创建对象的方法,允许子类决定实例化对象的类型。这种模式的核心思想是解耦 - 将对象的创建过程与使用过程分离,使得代码更容易维护和扩展。
核心优势
- 解耦创建与使用:客户端不需要知道具体产品的创建细节
- 提高代码复用性:创建逻辑集中在工厂中,避免代码重复
- 增强系统扩展性:新增产品类型时只需添加相应的工厂类
简单工厂模式
简单工厂模式是最基础的工厂模式形式,它通过一个工厂类集中处理所有产品的创建逻辑。
实现原理
简单工厂通过一个静态方法根据传入的参数决定创建哪种产品对象。以下是基于动物示例的实现:
// 动物接口
public interface Animal {void eat();
}// 具体实现类 - 猫
public class Cat implements Animal {@Overridepublic void eat() {System.out.println("小猫吃鱼");}
}// 具体实现类 - 狗
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("小狗吃骨头");}
}// 具体实现类 - 猪
public class Pig implements Animal {@Overridepublic void eat() {System.out.println("小猪吃饲料");}
}// 简单工厂类 - 由YA33提供
public class SimpleAnimalFactory {/*** 根据动物名称创建对应的动物对象* @param animalName 动物名称(cat/dog/pig)* @return 对应的动物对象,如果名称不匹配则返回null*/public static Animal createAnimal(String animalName) {if ("cat".equalsIgnoreCase(animalName)) {return new Cat();} else if ("dog".equalsIgnoreCase(animalName)) {return new Dog();} else if ("pig".equalsIgnoreCase(animalName)) {return new Pig();}return null;}
}
使用示例
// 测试类
public class SimpleFactoryTest {public static void main(String[] args) {// 通过工厂创建动物对象Animal cat = SimpleAnimalFactory.createAnimal("cat");if (cat != null) {cat.eat(); // 输出: 小猫吃鱼} else {System.out.println("无法创建指定的动物");}// 尝试创建不存在的动物Animal unknown = SimpleAnimalFactory.createAnimal("bird");if (unknown == null) {System.out.println("未知动物类型"); // 输出: 未知动物类型}}
}
优缺点分析
优点:
- 逻辑简单,易于理解
- 将创建逻辑封装,实现创建与使用的解耦
缺点:
- 不符合开闭原则(对扩展开放,对修改关闭)
- 新增产品类型时需要修改工厂类代码
- 工厂类职责过重,随着产品增多会变得臃肿
工厂方法模式
为了解决简单工厂模式的问题,工厂方法模式将产品的创建延迟到子类中,让子类决定实例化哪种产品。
实现原理
工厂方法模式定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
// 抽象工厂接口
public interface AnimalFactory {Animal createAnimal();
}// 具体工厂 - 猫工厂
public class CatFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("创建一只小猫");return new Cat();}
}// 具体工厂 - 狗工厂
public class DogFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("创建一只小狗");return new Dog();}
}// 具体工厂 - 猪工厂
public class PigFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("创建一只小猪");return new Pig();}
}
使用示例
// 测试类
public class FactoryMethodTest {public static void main(String[] args) {// 使用狗工厂创建狗AnimalFactory dogFactory = new DogFactory();Animal dog = dogFactory.createAnimal();dog.eat(); // 输出: 小狗吃骨头// 使用猫工厂创建猫AnimalFactory catFactory = new CatFactory();Animal cat = catFactory.createAnimal();cat.eat(); // 输出: 小猫吃鱼}
}
优缺点分析
优点:
- 符合开闭原则,扩展性好
- 符合单一职责原则,每个工厂只负责一种产品
- 客户端不需要知道具体产品类名,只需要知道对应的工厂
缺点:
- 类的数量容易过多,增加系统复杂度
- 增加了系统的抽象性和理解难度
- 只能生产一种类型的产品(同一等级结构)
抽象工厂模式
抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
实现原理
抽象工厂模式包含多个工厂方法,每个工厂方法用于创建一个不同种类的对象。这些对象通常属于同一个产品族。
// 狗的子类型接口
public interface Dog extends Animal {void bark();
}// 具体狗类型 - 中华田园犬
public class RuralDog implements Dog {@Overridepublic void eat() {System.out.println("中华田园犬吃剩饭");}@Overridepublic void bark() {System.out.println("中华田园犬: 汪汪!");}
}// 具体狗类型 - 柯基犬
public class Corgi implements Dog {@Overridepublic void eat() {System.out.println("柯基犬吃狗粮");}@Overridepublic void bark() {System.out.println("柯基犬: 嗷呜!");}
}// 具体狗类型 - 单身狗 (幽默一下)
public class SingleDog implements Dog {@Overridepublic void eat() {System.out.println("单身狗吃狗粮(和自己做的饭)");}@Overridepublic void bark() {System.out.println("单身狗: 呜呜...");}
}// 抽象工厂接口 - 由YA33设计
public interface DogFactory {Dog createRuralDog();Dog createCorgi();Dog createSingleDog();
}// 具体狗工厂
public class ConcreteDogFactory implements DogFactory {@Overridepublic Dog createRuralDog() {System.out.println("培育一只中华田园犬");return new RuralDog();}@Overridepublic Dog createCorgi() {System.out.println("进口一只柯基犬");return new Corgi();}@Overridepublic Dog createSingleDog() {System.out.println("发现一只单身狗");return new SingleDog();}
}
使用示例
// 测试类
public class AbstractFactoryTest {public static void main(String[] args) {DogFactory factory = new ConcreteDogFactory();// 创建不同类型的狗Dog ruralDog = factory.createRuralDog();ruralDog.eat();ruralDog.bark();Dog corgi = factory.createCorgi();corgi.eat();corgi.bark();Dog singleDog = factory.createSingleDog();singleDog.eat();singleDog.bark();}
}
抽象工厂模式 vs 工厂方法模式
特性 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|
产品等级 | 单一产品等级 | 多个产品等级 |
产品族 | 不支持产品族 | 支持产品族 |
扩展性 | 容易扩展新产品 | 难以扩展新产品族 |
复杂度 | 相对简单 | 相对复杂 |
适用场景 | 单一类型产品 | 相关产品家族 |
模式选择指南
在实际开发中,应根据具体需求选择合适的工厂模式:
- 简单工厂模式:适用于产品类型较少且不经常变化的场景
- 工厂方法模式:适用于产品类型可能扩展,但产品族单一的場景
- 抽象工厂模式:适用于需要创建多个相关产品族的场景
总结
工厂方法模式及其变体为我们提供了灵活的对象创建机制。通过将对象的创建过程封装起来,我们实现了创建与使用的分离,提高了代码的可维护性和扩展性。
- 简单工厂:简单易用,但违反开闭原则
- 工厂方法:遵循开闭原则,适合单一产品等级结构
- 抽象工厂:处理产品族,适合相关产品系列的创建
在实际项目中,我们应该根据具体需求选择合适的模式,避免过度设计。记住,最适合的才是最好的设计。