当前位置: 首页 > news >正文

设计模式八股

设计模式

-1.设计原则

1.单一职责原则

单一职责原则:一个类或者模块只负责完成一个职责(或者功能)

一个类只负责完成一个职责或者功能。也就是说,不要设计大而全的类,要设计粒度小、功能单一的类。换个角度来讲就是,一个类包含了两个或者两个以上业务不相干的功能,那我们就说它职责不够单一,应该将它拆分成多个功能更加单一、粒度更细的类。

评价一个类的职责是否足够单一,我们并没有一个非常明确的、可以量化的标准,可以说,这是件非常主观、仁者见仁智者见智的事情。实际上,在真正的软件开发中,我们也没必要过于未雨绸缪,过度设计。所以, 我们可以先写一个粗粒度的类,满足业务需求。随着业务的发展,如果粗粒度的类越来越庞大,代码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类。这就是所谓的持续重构(后面的章节中我们会讲到)。

2.开闭原则

“对扩展开放、对修改关闭”。添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。

怎么实现“对扩展开放、对修改关闭”?

在写代码的时候后,我们要多花点时间往前多思考一下,这段代码未来可能有哪些需求变更、如何设计代码结构,事先留好扩展点,以便在未来需求变更的时候,不需要改动代码整体结构、做到最小代码改动的情况下,新的代码能够很灵活地插入到扩展点上,做到“对扩展开放、对修改关闭”。

我们还要善于识别代码中的可变部分和不可变部分,把可变部分封装

0.设计模式的划分

1.1 根据模式的目的划分

根据模式是用来完成什么样的工作来划分,这种方法可分为创建型模式、结构型模式、行为型模式3种。

1.1.1 创建型设计模式

用于描述“怎么创建对象”。它的主要特点是“将对象的创建与使用分离”。如,单例、原型、工厂方法、抽象工厂、建造者等5种创建型模式。

创建型设计模式主要解决对象的创建问题,封装复杂的创建过程,以及解耦对象的创建代码和使用代码。其中,单例模式用来创建全局唯一的对象;工厂模式用来创建类型不同但相关的对象(继承同一父类或接口的一组子类),由给定的参数来决定创建哪种类型的对象:建造者模式用来创建复杂的对象,可以通过设置不同的可选参数,定制化地创建不同的对象;

1.1.2 结构型模式

用于描述“如何将类或对象按某种布局组成更大的结构”。如,代理、适配器、桥接、装饰、外观、享元、组合等7种结构型模式。

1.1.3 行为型模式

用于描述“类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责”。如,模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录模式、解释器等11中行为模式。

1.2 根据模式的作用划分

根据模式的主要用于类上还是主要用户对象上来分,这种方式可分为类模式和对象模式两种。

1.2.1 类模式

用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时便确定下来了。如,工厂方法、(类)适配器、模板方法、解释器等4种类模式。

1.2.2 对象模式

用户处理对象之间关系的,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。

类模式 工厂方法 (类)适配器 模板方法 解释器
对象模式 单例 原型 抽象工厂 建造者 代理 (对象)适配器 桥接 装饰 外观 享元 组合 策略 命令 职责链 状态 观察者 中介者 迭代器 访问者 备忘录

1. 工厂方法模式

1.什么是工厂模式?

工厂模式是一种创建型设计模式,它通过定义一个创建对象的接口来封装实例化对象的行为,让子类决定实例化哪一个类。

工厂模式的概念来源于传统的工厂生产流程,其主要目的是将对象的创建和使用分离,使得客户端不需要知道具体的产品类,只需通过工厂请求所需的产品即可。这样做的好处在于增加了系统的灵活性和可维护性,同时能够降低代码的耦合度。

2.工厂模式的具体作用

具体到工厂模式的作用,主要体现在以下几个方面:

  1. 解耦对象创建和使用过程:客户端代码不直接调用构造函数来创建对象,而是通过工厂类的接口来获取所需的对象,这样可以减少客户端与具体类之间的依赖关系。

  2. 降低重复代码:如果多个地方需要创建同一个复杂对象,可以通过工厂方法统一管理,减少重复的代码,并便于后期维护。

  3. 增强系统的扩展性:当系统需要新增产品时,只需要扩展新的工厂类而不用修改原有代码,符合开闭原则。

  4. 隐藏具体实现:客户端只关心产品的接口而不是具体的实现,使得在不改变客户端代码的情况下更换或者升级产品成为可能。

  5. 提高代码的可管理性和灵活性:通过工厂模式,可以方便地管理和切换不同的产品实现,适应业务需求变化。

总之,工厂模式不仅有助于构建清晰、易于维护和扩展的代码结构,而且能够在多产品或变体间提供灵活的切换机制,是面向对象设计中常用的一种高效设计模式。

将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。封装复杂的创建逻辑,调用者无需了解如何创建对象。

3.工厂模式的优缺点

工厂模式,特别是在软件工程中,主要目的是创建对象,同时将对象的创建过程和使用过程解耦。它包括几种不同的变体,如简单工厂、工厂方法、抽象工厂等。

工厂模式的优点主要包括

  1. 封装性:客户端代码不需要知道如何创建所需的对象,只需传递正确的参数即可获取需要的对象。

  2. 灵活性和可维护性:当添加新产品时,只需扩展工厂类而不必修改客户端代码,这符合开闭原则,即对扩展开放,对修改封闭。

  3. 隔离变化:工厂模式把对象创建过程中易变的部分隔离起来,有助于控制变化。

然而,工厂模式也有一些缺点

  1. 复杂性增加:由于引入了工厂类(在简单工厂模式中),系统的复杂性有所增加。尤其是在简单工厂模式中,如果产品类层次结构很复杂,那么工厂类的职责会变得沉重,因为它需要包含所有产品的创建逻辑。

  2. 违反单一职责原则:简单工厂模式可能会违反单一职责原则,因为工厂类既要负责创建对象,又要包含业务逻辑判断。

  3. 扩展困难:每次新增或者删除产品时,可能需要修改工厂类的代码,尤其是在简单工厂模式中,这一点尤为明显。

综上所述,工厂模式通过封装和隔离对象创建的细节,提供了一种灵活且易于维护的方式来管理对象的生命周期。但同时,它也增加了系统的复杂性并可能限制了其扩展性。在应用工厂模式时,应根据具体场景仔细考量这些优缺点,以实现最佳的设计决策。

单一职责原则

单一职责原则(Single Responsibility Principle,简称SRP)是面向对象编程中的一个重要设计原则。它的核心思想是:一个类或者模块应该只负责一项职责,如果有多个职责,就应该拆分成多个类或模块。

这个原则的主要目的是为了降低代码的复杂性,提高代码的可读性和可维护性。如果一个类承担了过多的职责,那么当其中一个职责发生变化时,可能会影响到其他的职责,这样就增加了代码的耦合度,降低了代码的可维护性。

例如,假设有一个类叫做“Employee”,它既负责处理员工的工资计算,又负责处理员工的考勤记录。那么当工资计算的规则发生变化时,可能会影响到考勤记录的功能,反之亦然。如果我们按照单一职责原则来设计,就应该将“Employee”类拆分为两个类,一个负责工资计算,一个负责考勤记录,这样就可以降低代码的耦合度,提高代码的可维护性。

开闭原则

开闭原则对扩展开放,对修改关闭在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级

4.3种工厂模式

三种工厂

  • 简单工厂模式

  • 工厂方法模式

  • 抽象工厂模式

1.2 简单工厂模式

简单工厂不是一种设计模式,反而比较像是一种编程习惯。把对象的

1.2.1 结构创建交给工厂类

简单工厂包含如下角色:

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

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

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

1.2.2 实现

现在使用简单工厂对上面案例进行改进,类图如下:

interface AbstractProduct{   public void dosomething();
}
class ConcretProduct1 implements AbstractProduct{   @Override   public void dosomething() {       System.out.println("1");   }
}
class ConcretProduct2 implements AbstractProduct{   @Override   public void dosomething() {       System.out.println("2");   }
}
//具体工厂
class Factory{   public AbstractProduct createProduct(String type){       AbstractProduct product = null;       if("concretProduct1".equals(type)){           product = new ConcretProduct1();       }else if("concretProduct2".equals(type)){           product = new ConcretProduct2();       }       return product;   }
}
public class Test {   //get方法必须要是static修饰的   public static AbstractProduct getProduct(String type){       Factory factory = new Factory();       AbstractProduct product = factory.createProduct(type);       return product;   }   public static void main(String[] args) {       AbstractProduct product = getProduct("concretProduct2");       product.dosomething();   }
}

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样也就解除了和Coffee实现类(具体产品)的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。

后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。

1.2.3 优缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

1.3 工厂方法模式

针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则。

1.3.1 概念

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

1.3.2 结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。

  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

1.3.3 实现

使用工厂方法模式对上例进行改进,类图如下:

流程:

代码如下:

interface AbstractProduct{   public void dosomething();
}
class ConcretProduct1 implements AbstractProduct{   @Override   public void dosomething() {       System.out.println("1");   }
}
class ConcretProduct2 implements AbstractProduct{   @Override   public void dosomething() {       System.out.println("2");   }
}
interface AbstractFactory{   public AbstractProduct createProduct();
}
//对应的具体工厂
class ConcretProduct1Factory implements AbstractFactory{   @Override   public AbstractProduct createProduct() {       return new ConcretProduct1();   }
}
class ConcretProduct2Factory implements AbstractFactory{   @Override   public AbstractProduct createProduct() {       return new ConcretProduct2();   }
}
public class Test {   private static AbstractFactory factory;   //构造函数指定某个工厂   public Test(AbstractFactory factory){
http://www.dtcms.com/a/360124.html

相关文章:

  • 算法题(196):最大异或对
  • 【系统分析师】高分论文:论网络系统的安全设计
  • 异步编程与面向对象知识总结
  • SDL3.0 学习随笔:其一
  • 暄桐:唯有认真思考过死亡,才足以应对日常
  • Deep Think with Confidence:llm如何进行高效率COT推理优化
  • Docker中Mysql容器忽略大小写
  • 卫星互联网:6G时代的关键基础设施与全球竞争格局
  • 记一次下载oneforall报错及解决方案
  • 企业数据湖:从混沌到秩序的分层设计与治理策略
  • 性能测试工具-SkyWalking
  • 事件驱动架构新范式:FastEvent 让领域事件开发变得优雅
  • 【HarmonyOS】天气预报 UI 的基本实现
  • KingbaseES JDBC 驱动详解:连接、配置与最佳实践
  • docker,数据卷
  • ES6 面试题及详细答案 80题 (13-21)-- 数组与字符串扩展
  • 【71页PPT】工业40及智能制造解决方案(附下载方式)
  • (LeetCode 每日一题) 36. 有效的数独 (数组、哈希表)
  • 决胜千里之外:服务器及硬件项目标书制作全流程与避坑指南
  • 基于OpenCv做照片分析应用一(Java)
  • More Effective C++ 条款20:协助完成返回值优化(Facilitate the Return Value Optimization)
  • MySQL—— 概述 SQL语句
  • obdumper和obloader迁移OceanBase业务库(一):实施手册
  • 项目-云备份
  • 自然语言处理NLP:嵌入层Embedding中input_dim的计算——Tokenizer文本分词和编码
  • Qt Demo之 deepseek 帮我写的关于双目标定的小界面
  • libmodbus移植
  • 面试问题详解十三:Qt 多线程同步【QReadWriteLock】讲解
  • Qt-Advanced-Docking-System: 一个基于 Qt 框架的高级停靠窗口系统
  • Qt libcurl的下载、配置及简单测试 (windows环境)