必考设计模式

news2024/11/26 11:26:22

文章目录

    • 一、单例模式(创建型)
        • 1、饿汉式
        • 2、懒汉式
        • 3、双重检验锁(DCL)
        • 4、sync.once实现单例
    • 二、工厂模式(创建型)
        • 1、简单工厂模式
        • 2、工厂方法模式
        • 3、抽象工厂模式(暂时不写)
    • 三、装饰模式(结构型)
    • 四、原型模式(创建型)
    • 五、观察者模式(行为)
    • 六、适配器模式(结构型)
    • 七、职责链模式(行为)
    • 八、迭代器模式(行为)
    • 九、生成器模式(创建型)

总共有22种设计模式,按照大类可分为:

行为模式:负责对象间的高效沟通和职责委派。
创建型模式:提供创建对象的机制, 能够提升已有代码的灵活性和可复用性。
结构型模式:介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。

一、单例模式(创建型)

1、饿汉式

package hungry

type singleton struct {}

// 在类加载时, 就已经初始化了, 如果singleton结
// 构体很大,那么如果用不到就初始化了,非常浪费资源
var instance = &singleton{}
func GetInstance() *singleton {
	return instance
}

2、懒汉式

package lazy

type singleton struct {}

var instance *singleton
// 在需要的时候才初始化, 避免浪费资源
func GetInstance() *singleton {
	// 加锁是为了解决并发问题
	m.Lock()
	defer m.Unlock()
	if instance == nil {
		instance = &singleton{}
	}
	return instance
}

上面这样加锁是可以解决问题,但是太重了, 程序性能下降很严重。因此出现了下面的double checking lock。

3、双重检验锁(DCL)

package dcl

import "sync"

type singleton struct {}

var instance *singleton
var m sync.Mutex
func GetInstance() *singleton {
	// 如果已经不为空就不进入加锁阶段了, 这样就优化了
	if instance == nil {
		m.Lock()
		defer m.Unlock()
		if instance == nil {
			// jvm new对象, 分为下面三步(即三个cpu指令)
			// 1. 给 instance 分配内存
			// 2. 调用 Singleton 的构造函数来初始化成员变量
			// 3. 将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)
			// 其中存在cpu指令重排、cpu cache的问题, 因此需要使用volatile修饰instance
			// 这样就会使用主存, 而不是使用cpu cache, 避免了指令重排的尴尬
			instance = &singleton{}
		}
	}
	return instance
}

golang内存模型:https://blog.csdn.net/Zerore/article/details/120321985,这一块目前还不太清楚,大致看了下,我觉得golang中也是存在指令重排的,可以使用sync.once原子语言解决指令重排。

4、sync.once实现单例

package once

import "sync"

type singleton struct{}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

二、工厂模式(创建型)

1、简单工厂模式

在这里插入图片描述

package simple

type Operator interface {
	GetResult() float64
	Init(numberA, numberB int)
}

// 运算类
type operation struct {
	NumberA int
	NumberB int
}

func (o *operation) Init(numberA, numberB int) {
	o.NumberA = numberA
	o.NumberB = numberB
}

type operationAdd struct {
	operation
}

func (a *operationAdd) GetResult() float64 {
	return float64(a.NumberA + a.NumberB)
}

type operationSub struct {
	operation
}

func (s *operationSub) GetResult() float64 {
	return float64(s.NumberA - s.NumberB)
}

// 简单工厂类
type CreateOperationFactory struct {
}

// 简单工厂类中只有一个根据参数生产对应产品的方法
func (cof *CreateOperationFactory) CreateOperate(operate string) Operator {
	var op Operator
	switch operate {
	case "+":
		op = &operationAdd{}
	case "-":
		op = &operationSub{}
	}
	return op
}

客户端代码:

package main

import (
	"fmt"
	"factory/simple"
)

func main() {
	cof := new(simple.CreateOperationFactory)
	op := cof.CreateOperate("-")
	op.Init(5, 2)
	fmt.Print(op.GetResult())
}

弊端:违反了开放-封闭原则(对扩展是开放的,而对修改是封闭的),每次增加新产品(比如增加乘除法支持)都需要修改工厂类中的switch语句。

2、工厂方法模式

为了符合开放-封闭原则,于是诞生了工厂方法模式。
核心思想:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类

package method

type Operator interface {
	GetResult() float64
	Init(numberA, numberB int)
}

type operation struct {
	NumberA int
	NumberB int
}

func (o *operation) Init(numberA, numberB int) {
	o.NumberA = numberA
	o.NumberB = numberB
}

type operationAdd struct {
	operation
}

func (a *operationAdd) GetResult() float64 {
	return float64(a.NumberA + a.NumberB)
}

type operationSub struct {
	operation
}

func (s *operationSub) GetResult() float64 {
	return float64(s.NumberA - s.NumberB)
}

// 相比简单工厂模式, 上面都是一模一样, 只是多了一堆
// 工厂子类, 创建获取产品对象的操作委托给了工厂子类去做
type IFactory interface {
	CreateOperation() Operator
}

type AddFactory struct {}

type SubFactory struct {}

func (af *AddFactory) CreateOperation() Operator {
	return &operationAdd{}
}

func (sf *SubFactory) CreateOperation() Operator {
	return &operationSub{}
}

客户端代码:

package main

import (
	"fmt"
	"design-mode/method"
)

func main() {
	var operFactory method.IFactory = &method.SubFactory{}
	oper := operFactory.CreateOperation()
	oper.Init(5, 2)
	fmt.Print(oper.GetResult())
}

3、抽象工厂模式(暂时不写)

三、装饰模式(结构型)

四、原型模式(创建型)

五、观察者模式(行为)

六、适配器模式(结构型)

七、职责链模式(行为)

八、迭代器模式(行为)

九、生成器模式(创建型)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13040.html

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

相关文章

高通SDX12:SFE(shortcut-fe)软加速驱动效果调测

背景 USB转PHY RTL8153不支持高通IPA硬加速,所以采用SFE软加速 调试设备为基于Cat.6通信模组的整机 SFE软加速前:UXM环境实际测速100Mbps,设备内部sirq 87% SFE软加速驱动调测 SFE驱动代码路径:sdx12-ap\shortcut-fe\shortcut-fe SFE驱动编译文件路径:sdx12-ap\poky\m…

阿里云ACP考试内容是什么?考试时间是什么时候?

对于现在的人来说,网络就是帮助自己了解世界的好帮手、就是让自己生活得更方便的好工具,这样一来,市场就需要大量的人才来满足需求,相对应的岗位也逐渐增多。于是就有大批的大学生在填报志愿的时候,选择IT专业&#xf…

使用Docker发布部署C# .NET core WebApi到服务器

1、启用Docker支持 如果我们使用vs2022新建WebApi项目的时候需要勾选 启用Docker : 如果没有勾选或者使用VS019创建的项目,可以在项目右键 添加 docker支持 2、发布运用程序 接下来开始发布程序,右键点击项目 发布 提示在哪里发布内容&am…

什么?console.log打印出的数据不对?

背景 都怪我年轻不懂事,调试代码只会用console.log。那么,就在今天,出事儿了! 看图说话。上面的111和222后面跟的数据竟然不一致? 在我的认知中,JSON里面的parse和stringify方法只是类型的转换啊&#xff…

深浅拷贝小整理(对象赋值请注意)

深浅拷贝小整理1. 一些基础知识 js数据类型分为基本数据类型>Number、String、Boolean、Null、Undefined和引用(对象)数据类型>Object包括有Function、Array、Date;基本数据类型存放在栈中,访问是按值访问;引用类型指的是对象&#xf…

痛定思痛!!!结合fidller抓包,简单介绍http请求报文和http响应报文

简单介绍http请求报文和http响应报文前言1. http请求报文的组成1.1 请求行的内容1.2 请求头的组成1.3 请求体2. HTTP响应报文组成前言 各类书上在介绍http请求报文和http响应报文时花的太过于专业,没有结合实际,当时读的时候可能是我太笨了,…

今天给在家介绍一篇健身俱乐部信息管理系统设计与实现

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

安装包UI美化之路-nsNiuniuSkin界面在线设计引擎

一年多前,我们自己开发了一个用于编辑、预览、调试nsNiuniuSkin的UI界面工具,越来越觉得好用,忍不住想要分享出来! 今天我把这个工具重新整理了一下,功能又完善了一些;下面就介绍一下这个工具的功能和使用…

深度解析:Web 3.0和元宇宙

导读:元宇宙的终极形态势必是去中心化的,而现在的网络生态并不能完全满足元宇宙去中心化的需求。一些人认为,即将到来的Web 3.0时代和元宇宙需要的网络生态高度重合。Web 3.0或许能够成为人类迈向元宇宙道路上重要的一步。 01 Web的三次技术迭代 Web 3.0通过新技术体现出来,…

蓝桥杯2022年第十三届决赛真题-围栏(求凸多边形的面积)

题目描述 这天,小明在造围栏。 他提前在地上 (二维平面) 打好了 n 个洞,这 n 个洞的位置形成了一个凸多边形。当他准备把固定围栏的木杆插进去的时候,突然发现自己少准备了两根木杆。 如图,他现在只能在这 n 个洞中选出 n − 2 …

【linux】软件管理

linux软件管理 文章目录linux软件管理桥接模式下配置虚拟机连接互联网nmcli相关命令windows和linux之间的FTPlinux中的软件包类型rpm相关命令搭建本地软件仓库测试本地仓库重新挂载仓库到http服务器上设置仓库镜像开机自动挂载dnf相关命令配置EPEL(Extra Packages f…

学生个人网页设计作品:旅游网页设计与实现——成都旅游网站4个页HTML+CSS web前端网页设计期末课程大作业 学生DW静态网页设计 学生个人网页设计作品

👨‍🎓静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计👩‍🎓,一般的网页作业需要融入以下知识点:div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

【YSYY】DSPE-PEG-Transferrin;DSPE-PEG-TF转铁蛋白的主动靶向介绍;磷脂-聚乙二醇-转铁蛋白

产品简称:DSPE-PEG-Transferrin;DSPE-PEG-TF 中文名称:磷脂-聚乙二醇转铁蛋白 产品全称: 1,2-dipalmitoyl-sn-glycero-3-phosphoethanolamine-N-(polyethylene glycol)-Transferrin 产品外观:白色固体 结 构 式&a…

Kubernetes NUMA 感知

TopologyManager TopologyManager 在1.18版本中处于 Beta 状态,该功能支持 CPU 和外围设备(例如 SR-IOV VF 和 GPU)的 NUMA 对齐,使工作负载能够在针对低延迟优化的环境中运行。 在引入 TopologyManager 之前,CPU 和…

2022-11-17 更高效的Cascades优化器 - Columbia Query Optimizer

在较早的文章中介绍了些Volcano/Cascades优化器框架的设计理念和实现思路,基本是基于论文的解读: https://zhuanlan.zhihu.com/p/364619893 https://zhuanlan.zhihu.com/p/365085770 虽然cascades号称目前最为先进的优化器搜索框架,但不得不说这2篇pa…

ZNS SSD是否真的前途一片光明?

引言 在上次存储随笔更新了一篇ZNS相关的文章“炙手可热的ZNS SSD将会为数据中心带来什么?”以后,在存储圈也一度引发关注。某公司相关同学也在朋友圈疯狂转发,让一些朋友误以为是存储随笔专为某公司写的技术推广软文。 借这个机会在这里再次…

【算法100天 | 20】有环/无环链表的相交问题(Java实现)

若两个链表相交,请返回相交的第一个节点。 给定两个有可能有环也有可能无环的单链表,头节点head1和head2。 实现一个函数,如果两个链表相交,请返回相交的第一个节点(从这个节点开始,后续结构都一样&#…

Leetcode-每日一题792. 匹配子序列的单词数(分桶)

题目链接:https://leetcode.cn/problems/number-of-matching-subsequences/description/ 思路 方法一、分桶 题目意思:给你一个字符串 s 和字符串数组 words, 可以对字符串 s 某些位置上的字符进行删除,并不改变原来的字符顺序…

什么是SIMD?

为了提高 CPU 指令处理数据的能力,半导体厂商在 CPU 中推出了一些可以同时并行处理多个数据的指令 ——SIMD指令。 百度百科定义为: SIMD全称Single Instruction Multiple Data,单指令多数据流,能够复制多个操作数,并…

新库上线 | CnOpenData中国核酸检测机构及采样点数据

中国核酸检测机构及采样点数据 一、数据简介 2020年1月21日,国家卫健委发布1号公告,将新型冠状病毒感染的肺炎纳入《中华人民共和国传染病防治法》规定的乙类传染病,并采取甲类传染病的预防、控制措施。目前,新型冠状病毒肺炎防控…