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

news2024/10/4 14:22:48

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

什么是设计模式

如果说代码是一道菜,那么设计模式就如同调料,合理使用可以使代码变得更加得精美;如果说代码是一堆积木,那么设计模式就是搭建积木的手册,合理使用可以使代码变成想要的形状。为了帮助各位了解什么是设计模式,我再举一个例子:
假设现在有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代码,
    在这里插入图片描述

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

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

其他示例代码:

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;
	}

	@Override
	public 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;
	}

	@Override
	public 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;
	}
	
	@Override
	public 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. 行为型设计模式

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

示例代码:

/**
 * 被观察者
 * @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<>();
	
	@Override
	public void registerObserver(Observer observer) {
		this.observers.add(observer);
	}
	
	@Override
	public void notifyObserver(String message) {
		for(Observer observer: observers) {
			observer.update(message); //更新观察者信息
		}
	}
}

/**
 * 观察者1
 * @author zygswo
 */
public class ConcreteObserverOne implements Observer{

	@Override
	public void update(String message) {
		System.out.println(message);
		System.out.println("observer1 is updated");
	}
}

/**
 * 观察者2
 * @author zygswo
 */
public class ConcreteObserverTwo implements Observer{

	@Override
	public 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.coloradmin.cn/o/2188171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据仓库!企业决策的智慧引擎

数据仓库&#xff01;企业决策的智慧引擎 前言数据仓库 前言 今数字化浪潮汹涌澎湃的时代&#xff0c;数据已然成为企业航行于市场海洋的罗盘&#xff0c;而数据仓库则是那承载罗盘的坚固船只。当我们深入探究数据仓库的世界&#xff0c;就仿佛打开了一扇通往企业智慧核心的大…

Gazebo环境下开源UAV与USV联合仿真平台

推荐一个ROS2下基于Gazebo环境的开源UAV与USV联合仿真平台。平台是由两个开源项目共同搭建的。首先是UAV仿真平台&#xff0c;是基于PX4官方仿真平台&#xff08;https://docs.px4.io/main/en/sim_gazebo_gz&#xff09;&#xff1b;其次是USV仿真平台&#xff0c;是基于VRX仿真…

C++语言学习(4): identifier 的概念

1. 什么是 identifier identifier 中文意思是标识符&#xff0c;在 cppreference 中明确提到&#xff0c;identifier 是任意长度的数字、下划线、大写字母、小写字母、unicode 字符 的序列&#xff1a; An identifier is an arbitrarily long sequence of digits, underscores…

FBX福币历史重演,ETH可能会在第四季度出现熊市

知名加密货币分析师Benjamin Cowen警告称&#xff0c;以太坊(ETH)可能在今年最后三个月突然转为看跌。FBX福币凭借用户友好的界面和对透明度的承诺,迅速在加密货币市场中崭露头角,成为广大用户信赖的平台。 考恩告诉他在社交媒体平台十、上的861500名粉丝表示&#xff0c;ETH可…

240 搜索二维矩阵 II

解题思路&#xff1a; \qquad 解这道题最重要的是如何利用从左到右、从上到下为升序的性质&#xff0c;快速找到目标元素。 \qquad 如果从左上角开始查找&#xff0c;如果当前matrix[i][[j] < target&#xff0c;可以向右、向下扩展元素都是升序&#xff0c;但选择哪个方向…

Python+Matplotlib创建高等数学上册P2页例2交互动画

import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider, CheckButtons# 创建图形和坐标轴 fig, ax plt.subplots(figsize(10, 8)) plt.subplots_adjust(left0.1, bottom0.2)# 设置图表 ax.set_xlim([-1.5, 1.5]) ax.set_ylim([-1.5, 1.5…

C(九)while循环 --- 军训匕首操情景

匕首操&#xff0c;oi~oi~oi~~~~~ 接下来的几篇推文&#xff0c;杰哥记录的是三大循环结构的运行流程及其变式。 本篇的主角是while循环。&#x1f449; 目录&#xff1a; while循环 的组成、运行流程及其变式关键字break 和 continue 在while 循环中的作用while 循环的嵌套题目…

MySQL中NULL值是否会影响索引的使用

MySQL中NULL值是否会影响索引的使用 为何写这一篇文章 &#x1f42d;&#x1f42d;在面试的时候被问到NULL值是否会走索引的时候&#xff0c;感到有点不理解&#xff0c;于是事后就有了这篇文章 问题&#xff1a; 为name建立索引&#xff0c;name可以为空select * from user …

SpringBoot线程问题

程序&#xff0c;线程&#xff0c;线程池 进程是资源分配最小单位&#xff0c;线程是程序执行的最小单位。计算机在执行程序时&#xff0c;会为程序创建相应的进程&#xff0c;进行资源分配时&#xff0c;是以进程为单位进行相应的分配&#xff0c;每个进程都有相应的线程&…

TiDB 7.x 源码编译之 TiFlash 篇

本文首发于TiDB社区专栏&#xff1a;https://tidb.net/blog/5f3fe44d 导言 TiFlash 从去年四月一日开源至今已经过去将近一年半&#xff0c;这段时间里 TiFlash 从 v6.0.0-DMR 升级到了 v7.3.0-DMR&#xff0c;并增加了若干新特性&#xff0c;比如支持 MPP 实现窗口函数框架&am…

sql-labs靶场第五关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①Order by判断列数 ②寻找注入方式 ③爆库&#xff0c;查看数据库名称 ④爆表&#xff0c;查看security库的所有表 ⑤爆列&#xff0c;查看users表的所有…

Linux之实战命令25:xargs应用实例(五十九)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

深度优先搜索:解锁无向图连通分量的编号策略

深度优先搜索:解锁无向图连通分量的编号策略 步骤:伪代码:C 代码实现:说明:在无向图中,深度优先搜索(DFS)是一种有效的算法,可以用来找出图的连通分量(Connected Components)。DFS 遍历图的过程中,可以自然地将图划分为若干棵树,这些树构成深度优先森林,其中每棵…

day03 笔试练习

1.简写单词 题目链接&#xff1a;简写单词_牛客题霸_牛客网 public static void main(String[] args) {Scanner sc new Scanner(System.in);while(sc.hasNext()){ // 输入多少读入多少char ch sc.next().charAt(0); // 提取首字母if(ch > a && ch < z){System…

netty之SpringBoot+Netty+Elasticsearch收集日志信息数据存储

前言 将大量的业务以及用户行为数据存储起来用于分析处理&#xff0c;但是由于数据量较大且需要具备可分析功能所以将数据存储到文件系统更为合理。尤其是一些互联网高并发级应用&#xff0c;往往数据库都采用分库分表设计&#xff0c;那么将这些分散的数据通过binlog汇总到一个…

第L9周:无监督学习|K-means聚类算法

本文为365天深度学习训练营 中的学习记录博客原作者&#xff1a;K同学啊 任务描述&#xff1a; ●学会调用sklearn实现KMeans算法。 ●了解误差平方和与轮廓系数。 1.聚类算法是什么&#xff1f; 聚类就是将一个庞杂数据集中具有相似特征的数据自动归类到一起&#xff0c;称为…

Leetcode 1498. 满足条件的子序列数目

1.题目基本信息 1.1.题目描述 给你一个整数数组 nums 和一个整数 target 。 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 由于答案可能很大&#xff0c;请将结果对 109 7 取余后返回。 1.2.题目地址 https://leet…

【优选算法之队列+宽搜/优先级队列】No.14--- 经典队列+宽搜/优先级队列算法

文章目录 前言一、队列宽搜示例&#xff1a;1.1 N 叉树的层序遍历1.2 ⼆叉树的锯⻮形层序遍历1.3 ⼆叉树最⼤宽度1.4 在每个树⾏中找最⼤值 二、优先级队列&#xff08;堆&#xff09;示例&#xff1a;2.1 最后⼀块⽯头的重量2.2 数据流中的第 K ⼤元素2.3 前 K 个⾼频单词2.4 …

气象网格数据与卫星轨道数据如何匹配??

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

IDEA里面的长截图插件

1.我的悲惨经历 兄弟们啊&#xff0c;我太惨了&#xff0c;我刚刚在准备这个继承和多态的学习&#xff0c;写博客的时候想要截图代码&#xff0c;因为这个代码比较大&#xff0c;一张图截取不下来&#xff0c;所以需要长截图&#xff0c;之前使用的qq截图突然间拉胯&#xff0…