# 【笔记】大话设计模式21-23

news/2024/5/16 21:14:37/文章来源:https://blog.csdn.net/moneymyone/article/details/128697590

【笔记】大话设计模式21-23

文章目录

  • 【笔记】大话设计模式21-23
  • 单例模式
      • 21.1 Example
      • 21.2 定义
      • 21.3 Show me the code
        • 一般单例代码(**懒汉模式**)
        • 静态初始化(**饿汉模式**)
      • 21.4 总结
  • 22 桥接模式
      • 22.1 Example
      • 22.2 定义
      • 22.3 Show me the code
      • 22.4 总结
  • 23 命令模式
      • 23.1 Example
      • 23.2 定义
      • 23.3 Show me the code
      • 23.4 总结

单例模式

21.1 Example

这个很好理解,每个人都是唯一的实体,不允许影分身术,分裂成多个你出来。

所以,电脑和手机上,很多软件,都只能打开1个窗口,重复打开,也只会调用那个唯一的单例。

一般C#里,定义一个全局静态变量即可,每次判断这个变量有没有存在或者窗体有没有Disposed,存在则已经生成过单例了。

picture source : Refactoring.Guru

21.2 定义

单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

21.3 Show me the code

一般单例代码(懒汉模式)

代码中lock (syncRoot)是将当前变量锁定,阻塞其他线程;

该锁前后进行了2次判断,是因为如果在多线程程序中,两个进行同时判断了第一个if语句,则会同时进入加锁代码中,因为lock机制,只允许1个线程进入,另一个阻塞,所以当第一个线程创建实例后,第二个线程即便在lock中,也不会再次创建实例。

这种做法就是Double-Check Locking(双重锁定)。

class Singleton
{// 私有静态变量private static Singleton instance;  // 初始化一个锁变量private static readonly object syncRoot = new object();// 私有构造函数,不允许外部实例化private Singleton(){}public static Singleton GetInstance(){if (instance == null){lock (syncRoot){if (instance == null){instance = new Singleton();}}}return instance;}
}

静态初始化(饿汉模式

C#与公共语言运行库提供了“静态初始化”的方法,不需要编写线程安全代码,即可解决多线程环境下不安全问题。

解决了2个问题:全局访问、实例化控制

instance变量标记为readonly,只能在静态初始化期间或在类构造函数中分配变量,实例被加载时就将自己实例化

// sealed 阻止派生类,因为派生类可能会增加实例
public sealed class Singleton
{// 在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化private static readonly Singleton instance = new Singletion();private Singleton(){ }public static Singleton GetInstance(){return instance;}
}

21.4 总结

  • 饿汉模式:静态初始化的方式,类一加载就实例化对象,需要提前占用系统资源。
  • 懒汉模式:面临多线程访问的安全性问题,需要双重锁定,需要的时候才实例化。
  • 抽象工厂模式生成器模式原型模式都可以用单例实现。

22 桥接模式

22.1 Example

在阿三还在上大学的时候,那时候手机还是诺基亚、摩托罗拉等品牌兴盛的时候,那时候,不同手机的软件不能通用,需要去手机品牌官网指定的网站上下载,哪怕下载同一款软件。

现在安卓机就是这样,大家都是使用安卓的操作系统,接口都一样的,想要开发软件,就在统一接口下,开发自己的软件或者适配自己的机型就行了。

picture source : Refactoring.Guru

22.2 定义

合成/聚合复用原则(CARP):尽量使用合成/聚合,尽量不要使用类继承。

桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们可以独立地变化。

22.3 Show me the code

class Program
{static void Main(string[] args){Abstraction ab = new RefinedAbstraction();ab.SetImplementor(new ConcreteImplementorA());ab.Operation();ab.SetImplementor(new ConcreteImplementorB());ab.Operation();Console.Read();}
}class Abstraction
{protected Implementor implementor;public void SetImplementor(Implementor implementor){this.implementor = implementor;}public virtual void Operation(){implementor.Operation();}}class RefinedAbstraction : Abstraction
{public override void Operation(){implementor.Operation();}
}abstract class Implementor
{public abstract void Operation();
}class ConcreteImplementorA : Implementor
{public override void Operation(){Console.WriteLine("具体实现A的方法执行");}
}class ConcreteImplementorB : Implementor
{public override void Operation(){Console.WriteLine("具体实现B的方法执行");}
}

22.4 总结

  • 聚合表示一种弱的拥有关系,体现A对象可以包含B对象,但是B对象不是A对象的一部分;

  • 合成表示一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样;

  • 桥接模式就是实现系统可能有多角度分类,每一种分类可能都有变化,就把多角度分离出来让其对立变化,减少耦合。就像电脑硬盘、显卡、内存条等设备,都可以独立插拔安装,选用不同品牌的硬件。

    picture source : Refactoring.Guru

    其实就是实现上图的思维模式转变,将原本通过继承等耦合方式实现的重量子类,变成独立的维度类,降低耦合,同时增加了每个维度的类的扩展空间。

23 命令模式

亦称: 动作、事务、Action、Transaction、Command

23.1 Example

大头家旁边开了一家烧饼店,店家是小本经营,就一个摊位,没有座位等,大家排队买烧饼,买完就带回去吃。

但是这样有个缺陷,就是大家围成一圈买烧饼,纷纷告诉老板要什么口味的烧饼,老板一个人也记不住,很容易把刚烤好的烧饼给了后来的人,先来的人没买到,导致了和老板的冲突。

这就是“行为请求者”(买烧饼的人)和“行为实现者”(烧饼店老板)的紧耦合。

反观看有点餐机的店铺就不同了,每个客人点餐后,点餐请求加入到请求队列中,而且包含详细的点餐内容,店面老板按照请求队列做餐即可。老板都不用知道谁点的什么内容。这就实现了解耦。

picture source : Refactoring.Guru

23.2 定义

命令模式(Command):将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

23.3 Show me the code

class Program
{static void Main(string[] args){//开店前的准备Barbecuer boy = new Barbecuer();Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);Waiter girl = new Waiter();//开门营业 顾客点菜girl.SetOrder(bakeMuttonCommand1);girl.SetOrder(bakeMuttonCommand2);girl.SetOrder(bakeChickenWingCommand1);//点菜完闭,通知厨房girl.Notify();Console.Read();}
}//服务员
public class Waiter
{private IList<Command> orders = new List<Command>();//设置订单public void SetOrder(Command command){if (command.ToString() == "命令模式.BakeChickenWingCommand"){Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。");}else{orders.Add(command);Console.WriteLine("增加订单:" + command.ToString() + "  时间:" + DateTime.Now.ToString());}}//取消订单public void CancelOrder(Command command){orders.Remove(command);Console.WriteLine("取消订单:" + command.ToString() + "  时间:" + DateTime.Now.ToString());}//通知全部执行public void Notify(){foreach (Command cmd in orders){cmd.ExcuteCommand();}}
}//抽象命令
public abstract class Command
{protected Barbecuer receiver;public Command(Barbecuer receiver){this.receiver = receiver;}//执行命令abstract public void ExcuteCommand();
}//烤羊肉串命令
class BakeMuttonCommand : Command
{public BakeMuttonCommand(Barbecuer receiver): base(receiver){ }public override void ExcuteCommand(){receiver.BakeMutton();}
}//烤鸡翅命令
class BakeChickenWingCommand : Command
{public BakeChickenWingCommand(Barbecuer receiver): base(receiver){ }public override void ExcuteCommand(){receiver.BakeChickenWing();}
}//烤肉串者
public class Barbecuer
{public void BakeMutton(){Console.WriteLine("烤羊肉串!");}public void BakeChickenWing(){Console.WriteLine("烤鸡翅!");}
}

23.4 总结

  • 优点:
    • 命令行模式能较容易地设计一个命令队列;
    • 较容易地将命令记入日志;
    • 允许接受请求的一方决定是否否决请求;
    • 容易实现对请求的撤销、重做和延迟执行,比如数据回滚操作;
    • 加入新命令不影响其他类;
    • 将请求操作的对象与指导执行对象分开。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022这特殊的一年,再见!

望着窗外的夕阳以及还未完全融化的积雪&#xff0c;我想是时候给这特殊的一年写篇总结了。于是我翻看了2021年的&#xff0c;发现文末所定的2022年目标。终于明白为什么老人不玩手机可以坐一下午了&#xff0c;因为往事回想起来就和电视连续剧一样。年初参加了开运跑&#xff0…

基于python的人工智能数据处理常用算法

文章目录二分法求解最小二乘法曲线拟合最小二乘法的来历最小二乘法与曲线拟合多项式曲线拟合SciPy内置最小二乘法应用泰勒级数背景引入泰勒公式泰勒级数展开与多项式近似二分法求解 机器学习过程中往往会用到很多变量&#xff0c;而这些变量之间的复杂关系一般用非线性方程来&…

Spring入门-IOC/DI入门与使用文件配置管理(1)

文章目录Spring入门1&#xff0c;Spring介绍1.1 为什么要学?1.2 学什么?1.3 怎么学?2&#xff0c;Spring相关概念2.1 初识Spring2.1.1 Spring家族2.1.2 了解Spring发展史2.2 Spring系统架构2.2.1 系统架构图2.2.2 课程学习路线2.3 Spring核心概念2.3.1 目前项目中的问题2.3.…

通讯录最终版——动态存储+文件处理

最终版通讯录即从上一个版本修改过来先看总体代码&#xff0c;我们再看看差异ps&#xff1a;里面涉及到很多函数的使用&#xff0c;后续我会出专栏来书写这些函数的使用和实例&#xff0c;与常见错误大家可以通过https://cplusplus.com查找test.c#define _CRT_SECURE_NO_WARNIN…

String的不可变性

1.什么是不可变对象 如果一个对象在创建之后就不能再改变它的状态&#xff0c;那么这个对象是不可变的&#xff08;Immutable&#xff09;。不能改变状态的意思是&#xff0c;不能改变对象内的成员变量&#xff0c;包括基本数据类型变量的值不能改变&#xff0c;引用类型的变量…

C进阶:动态内存函数 malloc calloc realloc free及常见动态内存开辟错误

本文主要讲解动态内存开辟的有关知识。 目录 一.malloc 与 free 1.malloc 2.free 3.实例&#xff1a; 二.calloc 三.realloc 四.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态…

2023年java面试题之zookeeper基础2

一、请描述一下 Zookeeper 的通知机制是什么&#xff1f;Zookeeper 允许客户端向服务端的某个 znode 注册一个 Watcher 监听&#xff0c;当服务端的一些指定事件触发了这个 Watcher &#xff0c;服务端会向指定客户端发送一个事件通知来实现分布式的通知功能&#xff0c;然后客…

DFS排列组合与连通性

目录 一、前言 二、DFS与排列组合 1、DFS&#xff1a;自写排列算法1 &#xff08;1&#xff09;基础模板 &#xff08;2&#xff09;基于(1)输出前n个数任意m个都全排列 2、DFS&#xff1a;自写排列算法2&#xff08;这个写法更常见&#xff09; &#xff08;1&#xff…

五个了解自己天赋优势的分析工具(二)盖洛普优势测评

盖洛普优势测评 盖洛普优势识别器&#xff08;也叫克利夫顿优势评估&#xff09;&#xff0c;是盖洛普公司旗下⼀款王牌产品&#xff0c;是⼀个专⻔⽤来识别⼀个⼈隐形天赋、潜在优势、驱动⼒来源的⼯具&#xff0c;它可以帮助⼀个⼈科学认识⾃⼰。 它把⼈的思维⽅式、感受形…

PostgreSQL数据库FDW——Parquet S3 MultifileMergeExecutionStateBaseS3

MultifileMergeExecutionStateBaseS3和SingleFileExecutionStateS3、MultifileExecutionStateS3类不同&#xff0c;reader成员被替换为ParquetReader *类型的readers vector。新增slots_initialized布尔变量指示slots成员是否已经初始化。slots成员是Heap类&#xff0c;Heap用于…

我们怎样才能过好这一生?

文章目录1. 日拱一卒&#xff0c;功不唐捐1.1 适当的时候给自己一个奖励1.2 一个人可能走的更快&#xff0c;但一群人才能走的更远1.3 通过一些事情去逼自己一把1.4 从真理中去感悟1.5 当你面临绝路时2. 梦想的意义不在于实现3. 孤独4. 烦恼5. 别总说来日方长6. 忍和韧性7. 事情…

电路方案分析(十七)TI远程声控参考设计

远程声控参考设计 描述 CC2650远程控制设计为基于ZigBeeRF4CE™兼容的软件架构RemeTI™或蓝牙低能耗软件堆栈的快速测试、评估和开发远程控制应用程序提供了最佳基础。 该方案设计包含了CC2560远程控制的原理图和布局文件&#xff0c;以及一个演示了使用RF4CE和低能耗蓝牙的…

2023.1.15 学习周报

文章目录摘要文献阅读1.题目2.摘要3.介绍4.本文贡献5.PROPOSED METHOD5.1 Problem Formulation5.2 Personalized Time Intervals5.3 Embedding Layer5.4 Time Interval-Aware Self-Attention5.4.1 Time Interval-Aware Self-attention Layer5.4.2 Causality5.4.3 Point-Wise Fe…

java动态规划算法

使用场景 动态规划最重要的是转移方程&#xff0c;而转移方程需要递归和记忆化搜索产生的表&#xff0c;因此直接贴出转移方程是没什么用的&#xff0c;不探究如何从递归到记忆化搜索再到转移方程&#xff0c;还是很难想到怎么去得到转移方程。下面我们将从例子中探寻如何三步走…

Java9的新特性模块化(Module)

一、 模块化是什么&#xff1f; Java 9引入了模块化系统&#xff0c;称为"Java Platform Module System"&#xff08;JPMS&#xff09; 这个系统允许将Java程序分成模块&#xff0c;每个模块都有自己的规范&#xff0c;可以明确地声明它依赖于哪些其他模块&#xff…

【基础篇】3 # 数组:为什么很多编程语言中数组都从0开始编号?

说明 【数据结构与算法之美】专栏学习笔记 什么是数组&#xff1f; 数组&#xff08;Array&#xff09;是一种线性表数据结构。它用一组连续的内存空间&#xff0c;来存储一组具有相同类型的数据。 线性表和非线性表 线性表&#xff08;Linear List&#xff09;&#xff1…

三维视觉 | 04 双目定位/测距原理

文章目录一、双目视觉模型二、双目标定三、消除畸变与图像校正&#xff08;1&#xff09; 图像校正&#xff08;2&#xff09;图像校正四. 双目匹配一、双目视觉模型 由上一节&#xff1a;摄像机原理及坐标系转换 可知&#xff0c;单个相机的像素坐标系与相机坐标系的关系为&a…

【ROS2 入门】ROS 2 actions 概述

大家好&#xff0c;我是虎哥&#xff0c;从今天开始&#xff0c;我将花一段时间&#xff0c;开始将自己从ROS1切换到ROS2&#xff0c;在上一篇中&#xff0c;我们一起了解ROS 2中Parameters&#xff0c; 这一篇&#xff0c;我们主要会围绕ROS中另外一个重要的概念“Actions ”来…

字节面试官: 让你设计一个MQ每秒要抗几十万并发,怎么做?

目录 1、页缓存技术 磁盘顺序写2、零拷贝技术3、最后的总结 这篇文章来聊一下Kafka的一些架构设计原理&#xff0c;这也是互联网公司面试时非常高频的技术考点。 Kafka是高吞吐低延迟的高并发、高性能的消息中间件&#xff0c;在大数据领域有极为广泛的运用。配置良好的Kaf…

C进阶_字符串库函数

目录 求字符串长度 strlen 常规实现 递归实现 指针-指针实现 长度不受限制的字符串函数 strcpy 模拟实现strcpy strcat 模拟实现strcat strcmp 模拟实现strcmp 长度受限制的字符串函数 strncpy strncat strncmp 求字符串长度 strlen size_t strlen ( const c…