【27】23种设计模式

一、概述

这次来讲一下23种设计模式,这是老生常谈的话了,实际运用中,能熟练并且完全掌握的设计模式,大家估计都寥寥无几。首先需要明白一点,你认为的设计模式的作用是什么?不是别人认为的,也不是百度认为的。而我认为的设计模式,是为了提供给我们更好的在开发设计中,让功能具有可扩展性,灵活性,可复用性的方法。也许在不断地了解这些模式之后,会对这个认识不断优化,得出你最终认为的价值。

如果按照以往方式去讲设计模式,估计就不用讲了,我认为菜鸟教程已经把23种设计模式讲的很明白,大家也可以直接去看教程。因此,这次我决定换个方式来讲一下23种设计模式的应用。让大家看看源码当中是如何运用这些设计模式的。

二、设计模式

由于只是了解设计模式,在贴源码的过程中,会有系统源码、第三方库源码、又或者省略很多关注设计中不重要的代码,可以根据贴的类名去查看源码文件。本次的讲的方式也会依照设计模式分类:创建、结构、行为分开进行书写。

1.单例模式

使用场景:用于创建唯一的对象实例,常见于管理全局状态或资源。
注意:虽然使用静态类也可以实现唯一实例,管理全局。但是在扩展方面:比如继承和多态,内存管理:比如延迟创建,垃圾回收,线程安全等都有限制。

	//WindowManagerGlobal.javaprivate WindowManagerGlobal() {}@UnsupportedAppUsagepublic static WindowManagerGlobal getInstance() {synchronized (WindowManagerGlobal.class) {if (sDefaultWindowManager == null) {sDefaultWindowManager = new WindowManagerGlobal();}return sDefaultWindowManager;}}

在WindowManagerImpl中,将操作View的行为交给了WindowManagerGlobal去操作,其中使用的就是单例模式。不过这里使用的(伪)双重锁的方式实现的单例模式,实际上的最佳实现还是使用静态内部类的方式实现单例模式,可以自行了解。

2.工厂模式

使用场景:用于创建对象,通常用户替代直接使用new关键字。
注意:这个模式的了解对后续的抽象工厂模式会有帮助。

//BitmapFactory.jvapublic static Bitmap decodeFile(String pathName) {return decodeFile(pathName, null);}public static Bitmap decodeResource(Resources res, int id) {return decodeResource(res, id, null);}public static Bitmap decodeStream(InputStream is) {return decodeStream(is, null, null);}

和传统的工厂模式有点点区别,这是通过提供多个静态接口来展现的工厂模式,根据传入的资源类型,创建不同的适配的bitmap对象。传统的工厂模式,可能根据传入的tag,name等等来判断创建不同的对象。

可以看到,工厂提供的产品是抽象的,具体的产品是外部使用者决定的,而不需要关注创建的细节,根据传入的参数,决定工厂创建什么具体产品返回。

3.抽象工厂模式

使用场景:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

//LayoutInflater.javapublic static LayoutInflater from(@UiContext Context context) {LayoutInflater LayoutInflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);if (LayoutInflater == null) {throw new AssertionError("LayoutInflater not found.");}return LayoutInflater;}public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {return inflate(parser, root, root != null);}

布局加载泵通过context#getSystemService就是一个创建抽象工厂创建具体工厂的过程,inflate像之前讲到的工厂模式,根据传入的布局xml解析的结果,创建不同的View。

4.建造者模式

使用场景:用于构建复杂对象的各个部分,并允许按步骤创建对象。

//AlertDialog.java
AlertDialog dialog = new AlertDialog.Builder(context).setTitle("Title").setMessage("Message").setPositiveButton("OK", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// Do something}}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {// Do something}}).create();
dialog.show();

这里直接给出了使用方式,更容易关注到建造的过程。建造者模式更适合建造出一个组合,各个建造过程中传入的对象都会在组合中承担角色。

5.原型模式

使用场景:用于创建重复的对象,同时又能保证性能。
注意:这里的例子涉及native层的拷贝,不能了解模式的使用过程,建议看菜鸟驿站的原型模式例子理解。

//Bitmap.javapublic Bitmap copy(@NonNull Config config, boolean isMutable) {checkRecycled("Can't copy a recycled bitmap");if (config == Config.HARDWARE && isMutable) {throw new IllegalArgumentException("Hardware bitmaps are always immutable");}noteHardwareBitmapSlowCall();Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable);if (b != null) {b.setPremultiplied(mRequestPremultiplied);b.mDensity = mDensity;}return b;}

这里强调是重复的对象,因为通过构造函数创建对象的过程中,会对字段逐个初始化,特别是对象比较复杂的情况下,克隆(拷贝)可以显著提高性能。

结构型

6.适配器模式

使用场景:用于将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。
注意:给出的是源码的使用方式,具体可以看JetPack#RecycleView的源码实现和使用方式。

//PopupWindowVisibility.javaArrayAdapter<String> autoAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, COUNTRIES);AutoCompleteTextView textView = findViewById(R.id.auto);textView.setAdapter(autoAdapter);

通过适配器接口,将用户输入的内容,转换成另一个接口适配的内容,这就是适配器工作的原理。

7.桥接模式

使用场景:用于将抽象部分与它的实现部分分离,使它们都可以独立的变化。

//RecyclerView使用private RecyclerView recyclerViewA;private RecyclerView recyclerViewB;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerViewA = findViewById(R.id.recyclerView1);recyclerViewA.setLayoutManager(new LinearLayoutManager(this));recyclerViewA.setAdapter(new OneItemAdapter(itemList));recyclerViewB = findViewById(R.id.recyclerView2);recyclerViewB.setLayoutManager(new LinearLayoutManager(this));recyclerViewB.setAdapter(new TwoItemAdapter(itemList));}

在分离抽象和实现的前提下,还有就是避免类爆炸,当一个类有多个维度的变化时,会导致类的数量急剧增加,这点很重要。使用桥接模式,我们只需要独立的扩展抽象部分和实现部分。

举例:一个图形类,它可以有不同颜色,或者再多一个维度,如果不使用桥接模式,我们就需要根据形状和颜色的这些维度组合进行排列组合,这样类的增加数量就是指数级的。

8.组合模式

使用场景:用于将对象组合成树形结构以表示“部分-整体”的层次结构。

//ViewGroup.java
@UiThread
public abstract class ViewGroup extends View implements ViewParent, ViewManager {@UnsupportedAppUsageprotected ArrayList<View> mDisappearingChildren;
}

ViewGroup本身继承View,管理了一个集合来存储它的子View。简化树形结构中对象的处理,无论它们是单个对象还是组合对象。

试想一下,建立的ViewTree,通过List管理ViewGroupA、ViewGroupB,它们每个视图组下,又有若干个其他的子视图View,它们当中也有的View可能是一个ViewGroup,包含其他的子视图View,形成的树形结构。

9.装饰器模式

//未完待续

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

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

相关文章

MATLAB被360误杀的解决方案

前面被误杀&#xff0c;今天又被误杀。 前面误杀结果是缺少文件&#xff0c;重装MATLAB也不行。 结果重装了操作系统。 这次&#xff0c;看到了提示额外小心。 当时备份了“病毒”文件&#xff0c;结果备份的也被杀了。 解铃还须系铃人 在360安全卫士里面恢复&#xff0c;步骤…

数据库管理-第225期 Oracle DB 23.5新特性一览(20240730)

数据库管理225期 2024-07-30 数据库管理-第225期 Oracle DB 23.5新特性一览&#xff08;20240730&#xff09;1 二进制向量维度格式2 RAC上的复制HNSW向量索引3 JSON集合4 JSON_ID SQL函数5 优化的通过网络对NVMe设备的Oracle的原生访问6 DBCA支持PMEM存储7 DBCA支持标准版高可…

PPT图表制作

一、表格的底纹 插入→表格→绘制表格→表设计→选择单元格→底纹 二、把一张图片做成九宫格 1. 把一张图片画成九宫格&#xff08;处理过后还是一张图片&#xff0c;但是有框线&#xff09; 绘制33表格→插入图片→全选表格单元格→右键设置形状格式→填充→图片或纹理填充…

前后端分离开发遵循接口规范-YAPI

目前&#xff0c;网站主流开发方式是前后端分离。因此前后端必须遵循一套统一的规范&#xff0c;才能保证前后端进行正常的数据&#xff08;JSON数据格式&#xff09;请求、影响&#xff0c;这套规范即是 YAPI. 产品经理撰写原型&#xff1b; 前端或后端撰写接口文档。 YAPI…

一座山城如何打造教育“一张网”

教育新基建作为国家新基建的重要组成部分,是实现教育高质量发展的基础支撑。2021年,教育部等六部门印发相关部署意见时明确提出:到2025年,基本形成结构优化、集约高效、安全可靠的教育新型基础设施体系。 在此宏观导向下,山城重庆积极响应,立足本地情况,开启了其特色化的探索之…

K8s对接Ceph-csi配置手册(附带踩坑记录以及解决方法)

目录 Ceph CSI (Container Storage Interface) CSI 的作用&#xff1a; 前提配置 版本信息 获取Ceph认证信息 获取Ceph集群Monitor信息 下载并部署Ceph CSI 如果此时全部显示错误&#xff0c;那就代表镜像拉取错误&#xff0c;此时执行的yaml脚本&#xff0c;通过yaml脚…

进行良好的文献综述能否提高学术研究的可信度

VersaBot一键生成文献综述 进行良好的文献综述 对于从多个方面提高学术研究的可信度至关重要&#xff1b; 1. 展示专业知识&#xff1a; 全面的回顾表明您对您所在领域的现有知识和相关理论有深入的了解。这将使您成为权威&#xff0c;并将您的研究置于更广泛的背景下。 2.…

ValueError: invalid literal for int() with base 10: ‘a‘

ValueError: invalid literal for int() with base 10: ‘a‘ 目录 ValueError: invalid literal for int() with base 10: ‘a‘ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff…

【CodinGame】趣味算法(教学用) CLASH OF CODE -20240730

文章目录 正文转换单位观察模式数字处理字符串处理 写在最后END 正文 转换单位 import sys import math# Auto-generated code below aims at helping you parse # the standard input according to the problem statement.n int(input()) for i in range(n):e int(input())…

win10 定时任务实战--开机启动 Java 应用

引言 在Windows 10系统中&#xff0c;可以通过结合任务计划程序&#xff08;Task Scheduler&#xff09;和批处理脚本&#xff08;.bat&#xff09;或PowerShell脚本来定期运行Java程序。以下是一个基本的步骤说明&#xff0c;展示如何设置这一过程。 第一步&#xff1a;准备…

爬虫“拥抱大模型”,有没有搞头?

验证码坐标识别 数据采集过程中&#xff0c;可能会碰到各种风控策略。其中&#xff0c;验证码人机验证是较为常见的&#xff0c;点选类验证码需要识别出相应的坐标&#xff0c;碰到这种情况&#xff0c;一般要么自己训练模型&#xff0c;要么对接打码平台。现在也可以将识别工…

多媒体技术:语音音频压缩

语音音频压缩 语音音频基础知识物理世界的声音——语音 语音音频编码方法波形编码波形编码原理常用波形编码技术脉冲编码调制PCM差分脉冲编码调制DPCM自适应差分脉冲编码调制ADPCM子带ADPCM 参数编码感知编码 语音音频编码框架语音编码框架音频编码框架混合编码框架 语音音频编…

JDK8的新特性

目录 接口的默认方法和静态方法 Lambda表达式1、匿名内部类2、函数式接口(FunctionalInterface)2.1 无参函数式接口匿名内部类方式-->Lambda表达式方式 2.2 有参函数式接口匿名内部类方式-->Lambda表达式方式 3、Lambda实战 3.1 循环遍历 3.2 集合排序 3.3 创建线程方…

黑马头条Day12-项目部署_持续集成

一、今日内容介绍 1. 什么是持续集成 持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff09;&#xff0c;指的是频繁地&#xff08;一天多次&#xff09;将代码集成到主干。 持续集成的组成要素&#xff1a; 一个自动构建过程&#xff0c;从检出代码、…

Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入

本教程主要实现【Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入】。 本文源码&#xff1a;https://gitee.com/songfayuan/go-zero-demo 教程源码分支&#xff1a;master 分支&#xff08;_examples/word-template/fill-word-template.go&#xff09; Golang处理…

Java-Swing开发-001组件

文章目录 Top-level containerJFrame容器对话框相关 JComponent组件面板相关文本相关菜单相关工具栏按钮下拉框进度条树形组件 Top-level container 1.JFrame 2.JDialog JFrame容器 //设置APP图标 this.setIconImage(new ImageIcon(getClass().getResource("/button/i…

论文解读(10)-图神经网络

加油&#xff0c;继续看论文。 这次学图神经网络&#xff0c;这个概念经常在其他论文里出现&#xff0c;所以我想先学习一下这方面的知识。 参考&#xff1a; 【图神经网络综述】一文道尽GNN原理、框架和应用-CSDN博客 【图神经网络】10分钟掌握图神经网络及其经典模型_图神经…

某“新一线城市“前端面试,纯纯被恶心到了

一.起因 在boss上刷到的一个小小厂&#xff0c;收大四全年实习生(web前端)&#xff0c;因为离家乡比较近&#xff0c;而且双非一本的学历以及入坑的时间没有太长(前端部分不到一年)&#xff0c;想去那里看看形势&#xff0c;要求是笔试面试&#xff0c;当场给是否录用结果&…

AgentBench: Evaluating LLMs As Agents

AgentBench: Evaluating LLMs As Agents Github&#xff1a; https://github.com/THUDM/AgentBench 榜单&#xff1a;https://llmbench.ai/agent/data demos&#xff1a;https://llmbench.ai/agent/demo 备注&#xff1a;该论文介绍为AgentBench v0.2版本 一、介绍 现如今&am…

三行代码高搞定nestjs静态图片映射方案

方案一 nestjs/serve-static 库映射 上代码 npm i nestjs/serve-staticimport { ServeStaticModule } from nestjs/serve-static; import { join } from path; const staticPath join(__dirname, .., /public/);Module({imports: [ServeStaticModule.forRoot({rootPath: sta…