前言
设计模式的六大原则
SOLID + 迪米特拉原则
单一职责原则(SRP)
开闭原则(OCP):一个软件实体如类、模块和函数应该对修改封闭,对扩展开放。
里氏替换原则(LSP):一个对象在其出现的任何地方,都可以用子类实例做替换,并且不会导致程序的错误
接口隔离原则(ISP):一个类不应该依赖它不需要的接口方法(功能)
依赖倒置原则(DIP):抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对抽象(接口)编程,而不是针对实现细节编程。
迪米特拉原则:也叫最少知道原则,迪米特法则的目的在于降低类之间的耦合。迪米特原则核心指导思想为只和直接朋友通信( 成员对象、方法参数、方法返回值;值出现在局部变量的类 ,不是直接朋友)
所有的设计模式都是为了程序能更好的满足这六大原则
GoF23种设计模式具体内容
| 类别 | 名称 | 开始时间 | 结束时间 | 天数 | 状态 | 示例 | 优点 | 缺点 | 适用场景 | 总结 |
|---|---|---|---|---|---|---|---|---|---|---|
| 创建型 | 简单工厂 | 2024-04-15 | 2024-04-15 | 1 | 完成 | 水果生产 | 1、工厂类可能过于庞大,承担过多职责,变成超级类(违反单一职责)。 2、新增新产品时,需要修改工厂类分支,违反开闭原则。 | 简单工厂模式就是让一个工厂类承担构建所有对象的职责,调用者需要什么产品,让工厂生产出来即可 | ||
| 工厂方法 | 2024-04-15 | 2024-04-15 | 1 | 完成 | 水果生产 | 工厂不能统一管理和快速替换,可能不同工厂之间创建的方法不一样,如苹果工厂创建苹果方法叫createApple(),返回值为Apple;梨工厂创建梨方法叫createPear(),返回值为Pear;替换时改动大 | 为了解决简单工厂模式弊端,工厂方法每个工厂生产一种水果,修改生产方式只需要修改特定工厂;新增水果只需要新增特定工厂。 | |||
| 抽象工厂方法 | 2024-04-16 | 2024-04-16 | 1 | 完成 | 水果生产 | 为了解决工厂方法弊端,抽象工厂方法将工厂抽象,将方法统一定义在接口中,实现抽象工厂的具体工厂接口方法出入参都一样,所以非常容易替换 | ||||
| 单例(饿汉) | 2024-04-16 | 2024-04-16 | 1 | 完成 | 一群人吃一个苹果 场景1:苹果已存在,饿了直接拿来吃(饿汉); | 现成的,要吃的时候直接拿 | 需要用东西存放,浪费资源(会在类加载之后立即创建出来,占用一块内存,并增加类初始化时间) | 在类加载时初始化实例,将并发安全交由JVM保证 | ||
| 单例(懒汉) | 2024-04-17 | 2024-04-17 | 1 | 完成 | 一群人吃一个苹果 场景2:苹果还不存在,饿了需要种出来才能吃(懒汉); | 需要吃的时候才生产,避免浪费资源(按需加载,避免内存浪费,减少了类初始化时间) | 要等生产好,这段时间就挨饿了 | 2种保证并发安全实现: 双检锁 静态内部类 | ||
| 建造者 | 2024-04-18 | 2024-04-18 | 1 | 完成 | 制作奶茶 | 要什么就加什么,不用担心忘了指定某个配置 1、对于复杂的对象构建十分有利 2、对于可能很多字段可选的对象构建十分有利 | 复杂的对象构建,可能有多个可选字段 | 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示 | ||
| 原型 | 2024-04-18 | 2024-04-18 | 1 | 完成 | 制作奶茶:粉丝要喝和杰伦一样的奶茶 | 创建对象时,需要从其他对象拷贝 | ||||
| 结构型 | 适配器 | 2024-04-22 | 2024-04-22 | 1 | 完成 | 通过适配器将220V家庭电压转换为5V充电电压进行手机充电 | 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作 | |||
| 桥接 | 2024-04-23 | 2024-04-23 | 1 | 完成 | 绘制不同形状、颜色、大小的图案 | 形状、颜色和大小都是图形的属性,他们的关系是平等的,不属于继承关系,更好的实现方式是:将形状、颜色和大小分离,根据需要对形状、颜色和大小进行组合,这就是桥接模式的思想 | 主要用于通过两个或多个同等级的接口组合成一个完整对象 | 将子类的区别方式(本实例中颜色)分离成接口,通过组合的方式桥接颜色和形状。 | ||
| 组合 | 2024-04-24 | 2024-04-24 | 1 | 完成 | 设计一个公司的人员分布结构 | 当整体和部分有相似的结构,在操作时可以被一致对待时,可以使用组合模式。比如文件夹和子文件夹的关系:文件夹中可以存放文件,也可以新建文件夹,子文件夹也一样;树枝和分树枝的关系,树枝可以长出叶子,也可以长出树枝,分树枝也一样。 | 区分于桥接模式,组合模式用于整体和部分关系的结构,桥接模式用于平等关系的结构。 | |||
| 装饰器(透明装饰,增强原有功能) | 2024-04-25 | 2024-04-25 | 1 | 完成 | 带上装饰品提高颜值的过程 | 定义功能接口,初始对象实现基础接口,装饰类在初始对象基础上增强方法功能 | I/O框架就是使用了装饰模式 | |||
| 装饰器(半透明装饰,添加新的功能) | 2024-04-25 | 2024-04-25 | 1 | 完成 | 房屋粘贴挂钩,新增挂东西功能 | 定义功能接口,初始对象实现基础接口,装饰类在初始对象基础上新增其他功能 | ||||
| 外观/门面 | 2024-04-25 | 2024-04-25 | 1 | 完成 | 每天上班前必须做的几件事,和每天下班必须做的几件事 | 把几个绑定的步骤封装成一个动作 的过程。比如要喝热水,正常需要烧水,用容器装热水,把热水倒入杯子中;而使用饮水机只需按热水键即可完成所有步骤。 | 尽量提供简洁的接口给别人调用 | |||
| 享元 | 2024-04-25 | 2024-04-25 | 1 | 完成 | 超级玛丽游戏,不同类型乌龟只需要改变颜色,游戏大小40KB | 共享对象,提高复用性,同Don't repeat yourself | ||||
| 代理(静态代理) | 2024-04-26 | 2024-04-26 | 1 | 完成 | Http请求前打印请求参数,接收到数据后打印响应结果 | 代理类提供被代理类等同的接口能力(只能补充能力,比如打印日志,不能删减) 1、如果同时代理多个类,会导致类无限制扩展。 2、如果类中有多个方法,同样的逻辑需要反复实现。比如HttpUtil中有其他方法,代理类不需要做其他内容,但也得定义方法供外部调用。 | 给某一个对象提供一个代理,并由代理对象控制对原对象的引用。区别于装饰模式,装饰模式是为了增强功能或添加功能(锦上添花),代理模式主要是为了加以控制(控制你帮我做一些事情) | |||
| 代理(动态代理)—JDK方式 | 2024-04-28 | 2024-04-28 | 1 | 完成 | Http请求前打印请求参数,接收到数据后打印响应结果 | 只能代理接口方法 | ||||
| 代理(动态代理)—CGLIB方式(Code Generation Library) | 2024-05-09 | 2024-05-09 | 1 | 可以使用同一个代理类来代理任意对象 | 打印日志 权限管理 Spring APO RPC | 相对于静态代理,动态代理更加灵活。不需要针对每个目标类都单独创建一个代理类,并且也不需要我们必须实现接口。常见的动态代理实现方式:JDK动态代理、GCLIB动态代理 | ||||
| 行为型:重点关注类与类之间的交互与协作 | 责任链模式 | 2024-05-12 | 2024-05-12 | 完成 | 不同能力的程序员解决bug | 1、降低了对象之间的耦合度。将请求的发送者和请求的处理者解耦。 2、扩展性强,满足开闭原则。可以根据需要增加新的请求处理类。 3、简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,避免了使用众多的条件判断语句。 4、责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。 | 不能保证每个请求一定被处理,该请求可能一直传到链的末端都得不到处理。 如果责任链过长,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链拼接次序错误而导致系统出错,比如可能出现循环调用。 | 拦截器 流程审批 处理客户投诉 加薪申请等 | 责任链主要用于处理职责相同,程度不同的类 | |
| 命令模式 | ||||||||||
| 解释器模式 | ||||||||||
| 迭代器模式 | ||||||||||
| 中介者模式 | ||||||||||
| 备忘录模式 | ||||||||||
| 观察者模式 | ||||||||||
| 状态模式 | ||||||||||
| 策略模式 | ||||||||||
| 模板方法模式 | ||||||||||
| 访问者模式 |
参考
如何学习设计模式:强推