工厂模式

工厂模式

三种工厂方式

​ 在java中,万物皆是对象,创建时如果直接new对象,就会使该对象耦合严重,假如需要更换对象,所有new对象的地方都需要该一遍,违反了设计模式开闭原则。如果使用工厂生产对象,我们只需要与工厂打交道,彻底的与对象解耦,如果需要更换对象,直接在工厂更换该对象即可,达到与对象解耦的目的,工厂模式巨大优点就是 : 解耦

  • 简单工厂模式 (不属于GOF 23种经典设计模式)
  • 工厂方法模式
  • 静态工厂方法

简单工厂模式

不是一种设计模式,像是一种约定。

结构

抽象产品:定义了产品规范,描述了产品主要功能和特性

具体产品:实现或者继承抽象产品的子类

具体工厂:提供了创建产品的方法,调用者通过调用该方法获取产品

示例

类图

简单工厂实现了对象的解耦合,需要对象只需要工厂去进行生产

image-20230526153324863

代码

咖啡类

1
2
3
4
5
6
7
8
9
10
public class Coffee {
public void getName(){}

public void addMilker(){
System.out.println("加牛奶");
}
public void addSugar(){
System.out.println("加糖");
}
}

拿铁

1
2
3
4
5
6
public class LatteCoffee extends Coffee{

public void getName() {
System.out.println("拿铁咖啡");
}
}

美式

1
2
3
4
5
public class AmericanCoffee extends Coffee{
public void getName(){
System.out.println("美式咖啡");
}
}

咖啡工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SimpleFactory {

public Coffee createCoffee(String type){
Coffee coffee = null;

if ("latte".equals(type)) {
coffee = new LatteCoffee();
}else if ("american".equals(type)) {
coffee = new AmericanCoffee();
}else{
throw new RuntimeException("没有"+type+"这个类型的咖啡");
}
coffee.getName();
coffee.addMilker();
coffee.addSugar();

return coffee;
}
}

咖啡商店

1
2
3
4
5
6
7
8
public class CoffeeStore {

public Coffee order(String type) {
SimpleFactory factory = new SimpleFactory();

return factory.createCoffee(type);
}
}
image-20230526161221823

例如上述例子,尽管使用简单工厂模式,实现了咖啡店点咖啡与具体咖啡之间的解耦合但是增加了咖啡工厂与具体咖啡之间耦合度,如果我们后续需要增加新品种的咖啡的话,还是需要去咖啡工厂里面去修改代码,违反了设计模式的开闭原则

静态工厂

静态工厂也不是23中设计模式中的,相较于上述简单工厂,只是工厂类中创建对象的方法变为了静态方法,不需要创建工厂对象,就可以使用工厂里的方法去拿到相应的产品对象

工厂方法模式

使用工厂方法模式可以完全遵守开闭原则

概念

定义一个用于创建对象的接口,让子类决定实例化哪类产品对象,工厂方法使一个产品类的实例化延迟到其他工厂的子类

结构

抽象工厂:提供创建产品接口,调用者通过访问具体工厂创建产品

具体工厂:主要实现抽象工厂的抽象方法,完成具体产品创建

抽象产品:定义产品规范,描述了产品主要功能和特性

具体产品:实现抽象产品角色所定义接口,由具体工厂创建,它同具体工厂之间一一对应

示例

类图

image-20230526173821557

代码

抽象咖啡工厂

1
2
3
public interface Factory {
Coffee createCoffee();
}

具体工厂

1
2
3
4
5
6
public class AmericanCoffeeFactory implements Factory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
1
2
3
4
5
6
public class LatteFactory implements Factory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
}

抽象产品

1
2
3
4
5
6
7
8
9
10
public class Coffee {
public void getName(){}

public void addMilker(){
System.out.println("加牛奶");
}
public void addSugar(){
System.out.println("加糖");
}
}

具体产品

1
2
3
4
5
6
public class LatteCoffee extends Coffee {

public void getName() {
System.out.println("拿铁咖啡");
}
}
1
2
3
4
5
public class AmericanCoffee extends Coffee {
public void getName(){
System.out.println("美式咖啡");
}
}

生产工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class CoffeeStore {
private Factory factory;

//选择需要创建哪一种咖啡工厂
public void setFactory(Factory factory){
this.factory = factory;
}

public void order(){
Coffee coffee = factory.createCoffee();
coffee.getName();
coffee.addMilker();
coffee.addSugar();
}
}

测试

image-20230526171117718

优缺点

优点:

  • 用户只需要具体工厂名称既可以创建具体产品,不需要知道创建细节
  • 在系统新增新的产品时,只需要新增新的具体产品类和新的具体抽象工厂,无需修改原来工厂,符合开闭原则

缺点:

  • 每增加一种产品就需要创建对应的产品和工厂,当产品比较多的时候,就会发生类爆炸的情况

抽象工厂模式

工厂方法模式:只生产同级别产品

抽象工厂模式:将考虑多级别产品的生产

image-20230526175210499

概念

是一种访问类提供一个创建一组相关或依赖对象接口,且访问类无需指定所需要产品具体类就能得到同族的不同等级的产品的模式结构

抽象工厂模式是工厂方法模式的升级,工厂方法模式只生产一个等级的产品,抽象工厂可以生产多个等级产品

结构

  • 抽象工厂:提供多个产品接口,它包含多个创建产品的方法,可以创建多个不同等级产品
  • 具体产品:主要实现抽象工厂的多个抽象方法,完成具体产品的创建
  • 抽象产品:定义产品规范,描述了产品主要特征和功能,抽象工厂模式有多个抽象产品
  • 具体产品:实现了抽象产品角色所定义接口,由具体工厂来创建,它同具体工厂之间是多对一的关系

示例

类图

image-20230526192635818

代码

产品

咖啡

1
2
3
4
5
6
7
8
9
10
public abstract class Coffee {
public void getName(){}

public void addMilker(){
System.out.println("加牛奶");
}
public void addSugar(){
System.out.println("加糖");
}
}
1
2
3
4
5
public class AmericanCoffee extends Coffee {
public void getName(){
System.out.println("美式咖啡");
}
}
1
2
3
4
5
public class LatteCoffee extends Coffee {
public void getName() {
System.out.println("拿铁咖啡");
}
}

甜品

1
2
3
public abstract class Dessert {
public abstract void show();
}
1
2
3
4
5
6
public class Mousse extends Dessert{
@Override
public void show() {
System.out.println("抹茶慕斯");
}
}
1
2
3
4
5
6
public class Tiramisu extends Dessert{
@Override
public void show() {
System.out.println("提拉米苏");
}
}

抽象工厂

1
2
3
4
public interface DessertFactory {
Coffee createCoffee();
Dessert createDessert();
}

美式工厂

1
2
3
4
5
6
7
8
9
10
11
12
public class AmericanDessertFactory implements DessertFactory{

@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}

@Override
public Dessert createDessert() {
return new Mousse();
}
}

意大利工厂

1
2
3
4
5
6
7
8
9
10
11
public class ItalyDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}

@Override
public Dessert createDessert() {
return new Tiramisu();
}
}

测试

image-20230526200104086

优缺点

优点:当一个产品族中多个对象设计在一起工作时,他能保证客户端始终使用同一个产品族中的对象

缺点:产品族需要增加一个新的产品时,所有工厂类都需要进行修改