什么是工厂模式?
工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。本文从一个具体的例子逐步深入分析,来体会三种工厂模式的应用场景和利弊。
1、简单工厂模式
什么是简单工厂模式?
简单工厂也叫做静态工厂,在程序编译成字节码文件前就已经确立了工厂类对一些对象的封装关系,只需要根据参数来获取工厂对象来获取对应的目标对象。
优点:
- 客户端创建对象时只需要记住特定的参数,而不需要记住复杂的类名,也不用关注实现的过程。(实现了封装和部分解耦)
- 创建对象不需要单独实例化,而是通过工厂类直接获取示例(实现复用)
缺点:
- 实例化对象的逻辑全部封装在一个工厂类里,每次需求变化都要单独修改工厂类(违反了开闭原则)。
- 不方便扩展子类
应用场景:
适合应用于业务简单产品较少且一旦创建完成不会再发生修改的情况
简单工厂逻辑结构图:
AbstractProduct: 抽象工厂就是把Product所有共性的方法抽取出来成为一个抽象类。
Product: 就是具体的产品类,拿手机来举例的话,那么ProductA好比就是苹果手机,ProductB就好比小米手机。
Factory: 就是对应Product的代工厂对象,工厂类,根据上面的举例对象来说,那么此时Factory就好比如富士康工厂,加工各种品牌的手机,可通过选择来选取加工不同品牌的手机。
具体实现:
接口Phone
👇
public interface Phone {
void makePhone();
}
具体实现类IPone
👇
public class IPhone implements Phone{
@Override
public void makePhone() {
System.out.println("生产苹果手机");
}
}
具体实现类MiPhone
👇
public class MiPhone implements Phone{
@Override
public void makePhone() {
System.out.println("生产小米手机");
}
}
工厂类PhoneFactory
👇
public class PhoneFactory {
public Phone getPhone(String type){
if ("IPhone".equals(type)){
return new IPhone();
}
if ("MiPhone".equals(type)){
return new MiPhone();
}
return null;
}
}
启动类
👇
public class Test {
public static void main(String[] args) {
PhoneFactory phoneFactory = new PhoneFactory();
Phone iPhone = phoneFactory.getPhone("IPhone");
Phone miPhone = phoneFactory.getPhone("MiPhone");
iPhone.makePhone();
miPhone.makePhone();
}
}
具体结果
👇
2、工厂方法模式
什么是工厂方法模式?
在现实生活中社会分工越来越细,越来越专业化,各种产品有专门的工厂生产,而不是像富士康一样包含了其他手机厂商的生产业务,而是每一个品牌都有自己的生产工厂。工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点:
- 类的个数容易过多,增加复杂度,增加了系统的抽象性和理解难度。
- 抽象产品只能生产一种产品。
使用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌。
工厂方法逻辑结构图:
AbstractProduct: 抽象的产品,抽取出该类产品共有的方法。
Product1: 具体的产品类,具体的产品生产细节在内部实现,比如IPhone。
Product2: 具体的产品类,具体的产品生产细节在内部实现,比如MiPhone。
AbstractFactory: 抽象工厂,抽取处所有工厂创建同一类产品的方法。
ConcreteFactory1: 具体的工厂类,一个工厂只能生产一类产品,比如IPhoneFactory工厂只能生产IPhone,MiPhoneFactory只能生产MiPhone。如果需要生产其他产品怎么办?此时只需要添加一个具体的产品类和对应的工厂即可。
ConcreteFactory2: 如上。
具体实现:
//抽象产品
public interface Phone {
void makePhone();
}
//具体产品IPhone
class IPhone implements Phone{
@Override
public void makePhone() {
System.out.println("生产苹果手机");
}
}
//具体产品MiPhone
class MiPhone implements Phone {
@Override
public void makePhone() {
System.out.println("生产小米手机");
}
}
//抽象工厂具有生产产品的方法
interface AbstractFactory {
public Phone createPhone();
}
//具体的苹果工厂
class IPhoneFactory implements AbstractFactory {
@Override
public Phone createPhone() {
return new IPhone();
}
}
//具体的小米工厂
class MiPhoneFactory implements AbstractFactory {
@Override
public Phone createPhone() {
return new MiPhone();
}
}
public class Test_gongchang {
public static void main(String[] args) {
IPhoneFactory iPhoneFactory = new IPhoneFactory();
Phone phone = iPhoneFactory.createPhone();
phone.makePhone();
MiPhoneFactory miPhoneFactory = new MiPhoneFactory();
Phone phone1 = miPhoneFactory.createPhone();
phone1.makePhone();
}
}
结果如下:
👇
3、抽象工厂模式
什么是抽象工厂模式?
上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品Phone。工厂方法模式引入工厂等级结构,解决了简单工厂模式中工厂类职责过重的问题,但由于工厂方法模式中每个工厂只创建一类具体类的对象,这将会导致系统当中的工厂类过多,这势必会增加系统的开销。此时,我们可以考虑将一些相关的具体类组成一个“具体类族”,由同一个工厂来统一生产,这就是我们本文要说的“抽象工厂模式”的基本思想。
优点:
- 增加新的产品等级很方便, 无须修改已有系统, 符合“开闭原则”。
- 分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。
缺点:
- 增加新的产品族结构麻烦, 需要对原有系统进行较大的修改, 甚至需要修改抽象层代码,这显然会带来较大的不便, 违背了“开闭原则”。因为抽象工厂接口确定了可以被创建的产品集合,所以难以扩展抽象工厂以生产新种类的产品。
应用场景:
- 一系列相关产品对象(属于同一产品族)一起创建时需要大量的重复代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现。
Attentions: 看到这里的朋友可能不太理解产品族和产品等级的概念。
注意它要来了!!!
产品等级: 产品等级即产品的继承结构,比如一个电视机的抽象类,其子类由海尔电视机、海信电视机、长虹电视机,抽象电视机与具体品牌的电视机形成了一个产品等级。
产品族: 在抽象工厂模式中,产品族是指由同一个工厂生产,但位于不同产品等级中的一组产品。如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
具体可参考:https://blog.youkuaiyun.com/w405722907/article/details/87798453
抽象工厂模式逻辑结构
AbstractPhone: 手机的抽象类,抽取手机的公共方法。
AbstractPC: 电脑PC端的抽象类,抽取手机的公共方法。
MiPhone和IPhone: 具体的手机实现类,属于不同产品族。
MiPC和MAC: 具体的电脑实现类,属于不同的产品族,但是MiPC和MiPhone属于同一产品组不同的产品级。MAC和IPone属于同一产品组不同的产品级。
AbstractFactory: 抽象工厂,抽取处创建具体产品的公共方法。
MiFactory和AppleFactory: 具体的工厂实现类,一个品牌工厂就是一个产品族。
具体实现
👇
//抽象的产品
interface Phone {
void makePhone();
}
//电脑接口
interface Computer {
void makeComputer();
}
//具体的产品类
class IPhone implements Phone {
public IPhone() {
this.makePhone();
}
@Override
public void makePhone() {
System.out.println("苹果工厂生产苹果手机");
}
}
//具体的产品类
class Mac implements Computer {
public Mac() {
this.makeComputer();
}
@Override
public void makeComputer() {
System.out.println("苹果工厂生产MAC");
}
}
//具体的产品类和上面的产品属于不同的族
class MiComputer implements Computer {
public MiComputer() {
this.makeComputer();
}
@Override
public void makeComputer() {
System.out.println("小米工厂生产笔记本电脑");
}
}
//具体的产品类和MiComputer属于同一产品族
class MiPhone implements Phone {
public MiPhone() {
this.makePhone();
}
@Override
public void makePhone() {
System.out.println("小米工厂生产小米手机");
}
}
//抽象工厂,抽取不同产品族的共性
interface AbstractFactory {
Phone createPhone();
Computer createComputer();
}
//具体的品牌工厂,一个品牌的所有展品就是一个产品族
class AppleFactory implements AbstractFactory {
@Override
public Phone createPhone() {
return new IPhone();
}
@Override
public Computer createComputer() {
return new Mac();
}
}
//具体的品牌工厂
class MiFactory implements AbstractFactory {
@Override
public Phone createPhone() {
return new MiPhone();
}
@Override
public Computer createComputer() {
return new MiComputer();
}
}
public class Testttt {
public static void main(String[] args) {
AppleFactory appleFactory = new AppleFactory();
appleFactory.createComputer();
appleFactory.createPhone();
MiFactory miFactory = new MiFactory();
miFactory.createComputer();
miFactory.createPhone();
}
}
运行结果
👇