23种设计模式

设计模式

  • 1.工厂模式
    • 1.1 简单工厂模式
    • 1.2 工厂方法模式
    • 1.3 抽象工厂模式
      • 1.3.1 扩展一个产品族
      • 1.3.2 扩展一个产品等级
    • 1.4 工厂方法模式和抽象工厂模式的区别

1.工厂模式

背景: 我们需要生产两款车: BMW320和BMW523
请添加图片描述

public class BMW320 {
}
public class BMW523 {
}

在没有工厂模式之前, 我们只能自己手动创建(new)这几款车

public static void main(String[] args) {BMW320 bmw320 = new BMW320();BMW523 bmw523 = new BMW523();
}

之后就出现了工厂, 使用工厂可以封装对象的创建逻辑,提高代码的灵活性、可维护性和可扩展性,同时降低客户端代码与具体产品类的耦合度。

1.1 简单工厂模式

请添加图片描述

代码改造:

  • 产品类: 继承同一个共性类(抽象类)
// 抽象类
abstract class BMW {
}
// 实现类
public class BMW320 extends BMW {
}
// 实现类
public class BMW523 extends BMW {
}
  • 工厂类: 提供创建产品的通用方法
public class Factory {public BMW createBMW(int type) {switch (type) {case 320:return new BMW320();case 523:return new BMW523();default:break;}return null;}
}
  • 生产者: 通过工厂获取对象
public static void main(String[] args) {Factory factory = new Factory();BMW bmw320 = factory.createBMW(320);BMW bmw523 = factory.createBMW(523);
}

简易工厂模式的优缺点:

  • 优点
    • 封装对象创建逻辑: 工厂封装了对象的创建逻辑, 生产者无需了解具体的对象创建逻辑.这提高了代码的可读性可维护性复用性
    • 松耦合: 生产者直接通过工厂来获取对象, 只需要知道产品类所需的具体参数即可
  • 缺点
    • 不符合开放-封闭原则: 当需要添加新的产品类时, 需要改动工厂类的代码, 违反了开发-封闭原则
    • 违背单一职责原则: 简单工厂模式通常将多个产品的创建逻辑都集中在一个工厂类中, 这可能导致该工厂类的职责过于庞大, 不符合单一职责原则

1.2 工厂方法模式

工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。
请添加图片描述

代码改造:

  • 产品类不改动
  • 工厂类: 工厂抽象化, 每新增一个产品, 只需要增加该产品的具体实现工厂类
interface FactoryBMW {BMW createBMW();
}
public class FactoryBMW320 implements FactoryBMW {@Overridepublic BMW320 createBMW() {return new BMW320();}
}
public class FactoryBMW523 implements FactoryBMW {@Overridepublic BMW523 createBMW() {return new BMW523();}
}
  • 生产者: 由具体工厂类决定要实例化的产品是哪个
public static void main(String[] args) {FactoryBMW320 factoryBMW320 = new FactoryBMW320();BMW320 bmw320 = factoryBMW320.createBMW();FactoryBMW523 factoryBMW523 = new FactoryBMW523();BMW523 bmw523 = factoryBMW523.createBMW();
}

工厂方法模式的优缺点:

  • 优点
    • 符合开发-封闭原则: 新增产品时只需要添加新的具体工厂类和产品类, 无需修改现有代码, 符合开放-封闭原则。
    • 遵循单一职责原则: 每个具体工厂类负责创建特定类型的产品, 符合单一职责原则, 使得系统更加模块化、清晰。
  • 缺点
    • 类的个数增加: 使用工厂方法模式会导致类的数量增加, 每个具体产品都需要对应一个具体工厂,这可能使得类的数量相对较多。
    • 不同的工厂类之间代码重复: 如果多个具体工厂类之间有相似的实现,可能导致代码的重复。在这种情况下,可以考虑使用抽象工厂模式来减少重复代码。

1.3 抽象工厂模式

在介绍抽象工厂模式前,我们先厘清两个概念:

  • 产品等级结构: 同一类型的产品
  • 产品族: 同一品牌的不同产品就构成了一个产品族
    在这里插入图片描述

横构图

请添加图片描述

竖构图

请添加图片描述

  • 产品类: 现在生产发动机A、B和空调A、B这四类产品
//发动机产品接口
public interface Engine {void create();
}  
public class EngineA implements Engine{  public void create() {  System.out.println("制造-->EngineA");  }  
}  
public class EngineB implements Engine{  public void create() {  System.out.println("制造-->EngineB");  }  
}//空调产品接口
public interface Aircondition {void create();
} 
public class AirconditionA implements Aircondition{  public void create() {  System.out.println("制造-->AirconditionA");  }  
}  
public class AirconditionB implements Aircondition{  public void create() {  System.out.println("制造-->AirconditionB");  }  
} 
  • 工厂类: 工厂接口类、工厂实现类
public interface Factory {  //制造发动机public Engine createEngine();//制造空调 public Aircondition createAircondition(); 
}
//为宝马320系列生产配件  
public class FactoryBMW320 implements Factory {     @Override  public Engine createEngine() {    return new EngineA();  }  @Override  public Aircondition createAircondition() {  return new AirconditionA();  }  
}  
//宝马523系列
public class FactoryBMW523 implements Factory {  @Override  public Engine createEngine() {    return new EngineB();  }  @Override  public Aircondition createAircondition() {  return new AirconditionB();  }  
}
  • 生产者
public class Customer {  public static void main(String[] args){  //生产宝马320系列配件FactoryBMW320 factoryBMW320 = new FactoryBMW320();  factoryBMW320.createEngine();factoryBMW320.createAircondition();//生产宝马523系列配件  FactoryBMW523 factoryBMW523 = new FactoryBMW523();  factoryBMW523.createEngine();factoryBMW523.createAircondition();}  
}

抽象工厂模式的缺点: 拓展一个产品等级很麻烦

1.3.1 扩展一个产品族

请添加图片描述
扩展一个产品族很简单, 例如新增一个BMW118的工厂, 只需再新增C类发动机和C类空调的实现类即可(新增一个产品族不需要修改原来的代码), 符合OCP原则

1.3.2 扩展一个产品等级

请添加图片描述
扩展一个产品等级结构是非常麻烦的, 除了新增产品接口、产品实现类以外, 你还需要修改原来的代码(工厂接口、每一个工厂实现类)

  • 淡黄色为新增的接口、实现类
  • 红色对原代码的修改

1.4 工厂方法模式和抽象工厂模式的区别

  • 适用场景不同
    • 工厂方法模式适用于单一产品等级结构, 一个工厂只创建一个具体产品
    • 抽象工厂模式 适用于多个产品等级结构, 一个工厂创建一整个产品族
  • 开发封闭原则
    • 工厂方法模式对工厂的扩展是开放的,对于产品等级结构的扩展是封闭的
    • 抽象工厂模式的扩展既对产品等级结构开放,也对产品族的扩展开放。