程序猿成长之路之设计模式篇——设计模式简介

devtools/2024/10/9 7:23:58/

无论是对于代码质量还是代码可维护性、可扩展性,使用合适的设计模式都能够起到促进提升的作用,此外在软考的软件工程师、系统架构师职称考试中,设计模式也是必考的一块内容,因此我打算开拓一个新的专栏简单介绍一下设计模式,梳理梳理一些重要的设计模式,帮助各位更好的了解各类型的设计模式以及使用不同类型的设计模式可以带来的好处。

什么是设计模式

如果说代码是一道菜,那么设计模式就如同调料,合理使用可以使代码变得更加得精美;如果说代码是一堆积木,那么设计模式就是搭建积木的手册,合理使用可以使代码变成想要的形状。为了帮助各位了解什么是设计模式,我再举一个例子:
假设现在有1和2两个数字,在不添加其他条件和环境的情况下这两个数字毫无相关性,但是现在有了运算符,有了数学公式,就可以将这两个数字联系起来了,就比如加法运算,1+2 = 3。其中1、2这两个数字可以理解成两个代码片段,而将两个数字相关联的公式可以理解成设计模式,通过设计模式可以将原本看上去不相关的代码片段联系起来,并产生我们想要的结果。

设计模式的好处

  1. 设计模式可以提高代码的可维护性及可扩展性,符合开闭原则(对扩展开放,对修改关闭)。举个例子,我们已经设计开发了一个类,并且该类符合单一职责原则(一个类仅仅满足实现一个特定的功能)就比如说要进行员工行为明细的录入,我们想在尽可能减少代码改动量和不改动原代码的前提下进行功能上的扩展,比如在录入之后还要对针对员工进行消息推送。这时候我们就可以使用适配器、装饰器或者代理设计模式。这样做的好处就是可以在不改动原来代码的基础上实现功能上的扩展。
  2. 设计模式可以保证数据的一致性。比如在项目范围内获取一个容器对象,并且要保证获取的容器对象是唯一的,这时候就可以使用单例设计模式
  3. 设计模式可以减少代码的修改量,比如我们使用组合策略,可以在只改动组合类的代码就可以实现代码的调整。
  4. 设计模式可以优化代码结构。

设计模式有哪些分类

  1. 创建型设计模式:提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用new 直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。常见的创建型设计模式有:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式、静态工厂模式。
  2. 结构型设计模式:这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。常见的结构型设计模式有:装饰器、适配器设计模式、外观设计模式、组合设计模式
  3. 行为型设计模式:关注行为本身的设计模式,比如关注观察者及被观察者通信的观察者设计模式,关注迭代器间调用的迭代器模式、关注不同行为响应策略的策略模式等。

用一个图片来整体描述一下设计模式之间的关系:
在这里插入图片描述

几类设计模式简介

  1. 创建型设计模式
    抽象工厂设计模式:不同工厂类中有不同的产品,但是产品类型是一致的,就比如说海尔有海尔工厂,西门子有西门子工厂,但是无论是海尔还是西门子都生产冰箱等家电产品。如下图所示,ProductA和ProductB都是抽象出来的产品类型,如冰箱和洗衣机,而ConcreteFactory1就可以是海尔集团,ConcreteFactory2就可以是西门子集团,那么ConcreteProductA1就是海尔生产的冰箱而ConcreteProductA2就是西门生产的冰箱,以此类推。
    在这里插入图片描述

  2. 结构型设计模式
    装饰器设计模式
    通过层层嵌套实现完整功能。采用了组合优于继承的策略。
    举例:java中的io代码,
    在这里插入图片描述

java">InputStream in = new FileInputStream("/test.txt");
InputStream bin = new BufferedInputStream(in);
byte[] data = new byte[128];
while(bin.read(data) != -1) {//...
}

其中in嵌套到BufferedInputStream中就用到了装饰器的嵌套,都是基于InputStream的实现类。

其他示例代码:

java">package decorator;
/*** 基础接口* @author zygswo**/
public interface BasePrinter {/*** 打印信息* @param msg*/void print();
}package decorator;/*** child接口* @author zygswo*/
public class ChildPrinter implements BasePrinter{/*** 打印日志*/protected volatile BasePrinter printer;/*** 构造方法* @param printer*/public ChildPrinter(BasePrinter printer) {this.printer = printer;}@Overridepublic void print() {System.out.println("ChildPrinter print start");printer.print();System.out.println("ChildPrinter print end");}
}
package decorator;
/*** parent接口* @author zygswo*/
public class ParentPrinter implements BasePrinter{/*** 打印日志*/protected volatile BasePrinter printer;/*** 构造方法* @param printer*/public ParentPrinter(BasePrinter printer) {this.printer = printer;}@Overridepublic void print() {System.out.println("ParentPrinter print start");printer.print();System.out.println("ParentPrinter print end");}
}package decorator;
/*** 接口传参类* @author zygswo*/
public class Printer implements BasePrinter{private String message;public Printer(String message) {this.message = message;}@Overridepublic void print() {System.out.println(message);}
}package decorator;public class Main {public static void main(String[] args) {BasePrinter myprinter = new Printer("hello world");//装饰器层层嵌套BasePrinter childPrinter = new ChildPrinter(new 		ParentPrinter(myprinter));childPrinter.print();}
}
  1. 行为型设计模式

观察者设计模式:通过设置观察者和被观察者,使得当被观察者的状态发生变化后,可以及时通知观察者。

示例代码:

java">/*** 被观察者* @author zygswo*/
public interface Subject{/*** 绑定观察者*/void registerObserver(Observer observer);/*** 通知观察者*/void notifyObserver(String message);
}/*** 观察者* @author zygswo*/
public interface Observer{/*** 更新观察者状态*/void update(Message message);
}/*** 被观察者* @author zygswo*/
public class ConcreteSubject implements Subject{private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {this.observers.add(observer);}@Overridepublic void notifyObserver(String message) {for(Observer observer: observers) {observer.update(message); //更新观察者信息}}
}/*** 观察者1* @author zygswo*/
public class ConcreteObserverOne implements Observer{@Overridepublic void update(String message) {System.out.println(message);System.out.println("observer1 is updated");}
}/*** 观察者2* @author zygswo*/
public class ConcreteObserverTwo implements Observer{@Overridepublic void update(String message) {System.out.println(message);System.out.println("observer2 is updated");}
}public class Main {public static void main(String[] args) {Subject subject = new Subject();subject.registerObserver(new ConcreteObserverOne());subject.registerObserver(new ConcreteObserverTwo());subject.notifyObserver("hello world");}
}

http://www.ppmy.cn/devtools/121665.html

相关文章

黑马JavaWeb开发跟学(九)MyBatis基础操作

黑马JavaWeb开发跟学九.MyBatis基础操作 1. Mybatis基础操作1.1 需求1.2 准备1.3 删除1.3.1 功能实现1.3.2 日志输入1.3.3 预编译SQL1.3.3.1 介绍1.3.3.2 SQL注入1.3.3.3 参数占位符 1.4 新增1.4.1 基本新增1.4.2 主键返回 1.5 更新1.6 查询1.6.1 根据ID查询1.6.2 数据封装1.6.…

【AI大模型-文心-思维树解读-总结的总结-最后】

提问&#xff1a;总结的总结&#xff0c;请根据我的 “”“什么是“”“思维树”“”模型框架 “”“&#xff0c;到最后”“” 好的&#xff0c;确认”"“仓颉精通之路”"“作为我们的”"“暗号”"" “”“&#xff0c;总结出我们对话的方法论 回答&…

Discord:报错:A fatal Javascript error occured(解决办法)

按 Windows 键 R 并输入 %appdata% 选择 discord 文件夹并将其删除。 再次按 Windows 键 R 并输入 %LocalAppData% 选择 discord 文件夹并再次将其删除。 附加&#xff1a; 如果还不行&#xff0c;就通过官网下载吧&#xff0c;这个问题通过epic下载可能会有

编码与解码

文章目录 编码与解码一、字节 & 字符二、编码 & 解码三、字符集 & 字符编码四、ASCII五、ISO-8859-1六、GB七、Unicode1、概述2、发展3、UTF-8 编码4、UTF-16 编码 八、Base64 编码1、概述2、原理3、代码示例 九、十六进制编码 编码与解码 一、字节 & 字符 字…

雷池 WAF 如何配置才能正确获取到源 IP

经常有大哥反馈说雷池攻击日志里显示的 IP 有问题。 这里我来讲一下为什么一些情况下雷池显示的攻击 IP 会有问题。 问题说明 默认情况下&#xff0c;雷池会通过 HTTP 连接的 Socket 套接字读取客户端 IP。在雷池作为最外层网管设备的时候这没有问题&#xff0c;雷池获取到的…

opencv:使用主成分分析PCA计算轮廓的偏转角度

PCA计算轮廓角度 (1)找图像中的轮廓(2)使用主成分分析PCA计算特征向量 总的来说&#xff0c;就是利用主成分分析方法得到轮廓的主特征向量&#xff0c;根据主特征向量来计算轮廓的角度 (1)找图像中的轮廓 读取图像&#xff0c;对图像进行HSV转换&#xff0c;使用明暗通道的图像…

【PostgreSQL】入门篇——索引:提高查询性能的利器

1. 索引的概念 描述 索引是数据库表中一个或多个列的值的有序列表。它类似于书籍的目录&#xff0c;可以帮助数据库快速定位到存储在表中的数据。 索引的主要目的是提高数据检索的速度&#xff0c;尤其是在处理大量数据时。 作用 加速查询&#xff1a;通过减少需要扫描的数…

坐标系变换总结

二维情况下的转换 1 缩放变换 形象理解就是图像在x方向和y方向上放大或者缩小。 代数形式&#xff1a; { x ′ k x x y ′ k y y \begin{cases} x k_x x \\ y k_y y \end{cases} {x′kx​xy′ky​y​ 矩阵形式&#xff1a; ( x ′ y ′ ) ( k x 0 0 k y ) ( x y ) \be…