今天来学习一个使用非常广泛、也非常有威力的设计模式–工厂模式,主要核心还是在于帮助我们针对抽象编程,而不是针对具体类编程。
从问题出发
- 简单工厂是什么?是不是一个设计模式?如果使用?
- 工厂方法是什么?抽象了什么?
- 抽象工厂是什么?抽象了什么?
- 工厂方法和抽象工厂的区别?
简单工厂模式
简单工厂不算是一个真正的设计模式,而更像是一种我们的编程习惯,但是在平时编码中这不失为一个简单的方法,可以将客户程序从具体类解耦。
介绍
工厂类拥有一个工厂方法(create),接受了一个参数,通过不同的参数实例化不同的产品类。
图示:
优缺点
- 优点:
- 很明显,简单工厂的特点就是“简单粗暴”,通过一个含参的工厂方法,我们可以实例化任何产品类,上至飞机火箭,下至土豆面条,无所不能。
- 所以简单工厂有一个别名:上帝类。
- 缺点:
- 任何”东西“的子类都可以被生产,负担太重。当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。
- 在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,无能为力。因为增加新产品只能通过修改工厂方法来实现。
工厂方法正好可以解决简单工厂的这两个缺点。接着往下看吧,通过这种层层递进的学习,你一定会理解的透彻。
小提示:spring中是通过配置文件和反射解决了简单工厂中的缺点。
如何使用
public class AnimalFactory {
//简单工厂设计模式(负担太重、不符合开闭原则)
public static Animal createAnimal(String name) {
if ("cat".equals(name)) {
return new Cat();
} else if ("dog".equals(name)) {
return new Dog();
} else if ("cow".equals(name)) {
return new Dog();
} else {
return null;
}
}
}
工厂方法
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。
图示
优缺点
- 优点
- 工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产;(对应简单工厂的缺点1。
- 同时增加某一类 ”东西“ 并不需要修改工厂类,只需要添加生产这类 ”东西“ 的工厂即可,使得工厂类符合开放-封闭原则。
- 缺点
- 对于某些可以形成产品族(一组产品)的情况处理比较复杂。
示例
// 抽象出来的动物工厂----它只负责生产一种产品
public abstract class AnimalFactory {
// 工厂方法
public abstract Animal createAnimal();
}
// 具体的工厂实现类
public class CatFactory extends AnimalFactory {
@Override public Animal createAnimal() {
return new Cat();
}
}
//具体的工厂实现类
public class DogFactory extends AnimalFactory {
@Override public Animal createAnimal() {
return new Dog();
}
}
抽象工厂模式
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车看作是另一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,而是一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的“抽象”指的是就是这个意思。 即相比于工厂方法,抽象工厂定义了一系列的产品,而不是一个产品。
上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。
图示
工厂模式区别
- 简单工厂 : 使用一个工厂对象用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
- 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
- 抽象工厂 : 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
今天新学习到的OO原则:依赖抽象,不要依赖具体类