介绍
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
总是引用接口而非实现类,能允许变换子类而不影响调用方,即尽可能面向抽象编程。
原理
工厂模式中主要有三种类型:
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
简单工厂模式(静态工厂方法)
简单工厂模式并不属于23种设计模式之一,它是工厂模式家族中最简单实用的模式。
简单工厂模式的工厂类负责创建不同类型的对象,它提供一个创建对象的静态方法,根据传入的参数不同返回不同的类实例。
我们使用MessageDigest
时,为了创建某个摘要算法,总是使用静态工厂方法getInstance(String)
:
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
调用方通过产品名称获得产品实例,不但调用简单,而且获得的引用仍然是MessageDigest这个抽象类。
简单工厂模式案例
接口
interface Animal {
/**
* 动物叫
*/
void cry();
static Animal judge(String name){
if ("狗".equals(name)){
return new Dog();
} else if ("猪".equals(name)) {
return new Pig();
}else {
return null;
}
}
}
实现类
class Dog implements Animal {
public void cry(){
System.out.println("狗叫");
}
}
class Pig implements Animal {
public void cry(){
System.out.println("猪叫");
}
}
调用
Animal.judge("狗").cry();
Animal.judge("猪").cry();
输出
狗叫
猪叫
工厂方法模式
工厂方法模式通过定义工厂方法来创建对象,而这个工厂方法可以被子类覆盖,从而改变所创建的对象类型。
一个工厂类对应一个产品类
工厂方法模式案例
接口
interface Animal {
/**
* 动物叫
*/
void cry();
}
实现类
class Dog implements Animal {
public void cry(){
System.out.println("狗叫");
}
}
class Pig implements Animal {
public void cry(){
System.out.println("猪叫");
}
}
工厂接口
public interface AnimalFactory {
Animal getAnimal();
}
工厂类
class DogFactory implements AnimalFactory {
@Override
public Animal getAnimal() {
return new Dog();
}
}
class PigFactory implements AnimalFactory {
@Override
public Animal getAnimal() {
return new Pig();
}
}
调用
AnimalFactory animalFactory= new DogFactory();
animalFactory.getAnimal("狗").cry();
输出
狗叫
抽象工厂模式
抽象工厂模式提供了一种将工厂与产品族的概念分离开来的方法,它能够创建一系列相关的对象,而无需指定它们的具体类。
一个品牌或者属性的所有产品(产品族) 对应 一个工厂负责生产(产品族)的所有产品
抽象工厂模式案例
接口
interface Animal {
/**
* 动物叫
*/
void cry();
}
interface Botany {
/**
* 植物动
*/
void move();
}
实现类
class Dog implements Animal {
public void cry(){
System.out.println("狗叫");
}
}
class Pig implements Animal {
public void cry(){
System.out.println("猪叫");
}
}
class Grass implements Botany {
public void move(){
System.out.println("草在动");
}
}
class GreenHat implements Botany {
public void move(){
System.out.println("绿帽子在动");
}
}
工厂类
interface Factory {
Animal getAnimal(String name);
Botany getBotany(String name);
}
// 草猪
class GrassPig implements Factory{
public Animal getAnimal(String name){
return new Pig();
}
public Botany getBotany(String name){
return new Grass();
}
}
// 绿帽子狗
class GreenHatDog implements Factory{
public Animal getAnimal(String name){
return new Dog();
}
public Botany getBotany(String name){
return new GreenHat();
}
}
工厂模式的优缺点
优点
- 可以隐藏创建实现类的过程,让代码更加简洁易懂
- 可以避免直接使用 new 关键字来创建对象,降低代码的耦合性
缺点
- 增加了代码的复杂度
- 增加了程序的抽象性和理解难度
简单工厂的优缺点
优点
- 简单上手
- 可以创建所有产品
缺点
- 如果需要增加额外的类,就违背了开闭原则
工厂方法的优缺点
优点
- 解决开闭原则的问题
缺点
- 一个工厂只能对应一个产品
- 当产品过多时,会出现类爆炸的问题
抽象工厂的优缺点
优点
- 解决了类爆炸的问题
缺点
- 如果需要增加额外的产品,就违背了开闭原则
注意事项(*
重点)
- 尽量使用工厂模式来创建对象,而不是直接使用 new 关键字
三者的区别
简单和抽象:违背了开闭原则
工厂方法:类爆炸的问题
简单工厂模式适用于创建逻辑简单的对象
工厂方法模式适用于创建单一类型的对象
抽象工厂模式适用于创建一组相关的产品对象
补充
由于抽象工厂并未解决开闭原则的问题,所以发明了超级工厂和容器工厂