还在埋头敲代码?不妨学学设计模式,必能让你工作事半功倍

news/2024/5/21 17:03:07/文章来源:https://blog.csdn.net/m0_62167422/article/details/127283222

设计模式在开发中占很重要的地位;在大型项目中使用好设计模式往往会取得事半功倍效果;下面就介绍下几种在开发中常用到的设计模式

装饰者模式(Decorator Pattern)

装饰者模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能;它是通过创建一个包装对象,也就是装饰来包裹真实的对象

特点

  • 装饰对象和真实对象有相同的接口;这样客户端对象就能以和真实对象相同的方式和装饰对象交互
  • 装饰对象包含一个真实对象的引用(reference)
  • 装饰对象接受所有来自客户端的请求;它把这些请求转发给真实的对象。
  • 装饰对象可以在转发这些请求以前或以后增加一些附加功能;这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能;在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展

何时使用

  • 需要扩展一个类的功能,或给一个类添加附加职责
  • 需要动态的给一个对象添加功能,这些功能可以再动态的撤销
  • 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实
  • 当不能采用生成子类的方法进行扩充时;一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类

优点

  • Decorator 模式与继承关系的目的都是要扩展对象的功能,但是 Decorator 可以提供比继承更多的灵活性
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合

缺点

  • 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性
  • 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂
  • 装饰模式是针对抽象组件(Component)类型编程;但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适;当然也可以改变 Component 接口,增加新的公开的行为,实现 “半透明”装饰者模式;在实际项目中要做出最佳选择

单例模式

单例模式是我们在开发种经常使用到的一种设计模式;单例模式创建的类在当前进程种只有一个实例,并有一个访问它的全局入口

优点

  • 内存中只有一个对象实例,节省了内存空间
  • 避免了频繁创建实例带来的性能消耗
  • 提供了一种全局访问入口,例如读取配置信息

缺点

  • 一般静态类不提供接口实现、抽象方法等功能,扩展能力差,修改的话只能在这个单例类里面进行
  • 由于静态模式使用了 static 全局变量,所以涉及生命周期的引用,这样很容易引起内存泄露,例如: 传入了一个Activity类,这个时候我们需要 传入的是跟static生命周期一样长的Application Context,否则就不要使用单例模式,例如Dialog对话就不要使用单例模式。

适用场景

  • 对象需要保存一些状态信息
  • 避免多重读写操作例如: 多个实例读取了同一资源文件,后续涉及对这个资源文件写入同步的操作

单例模式实现

//单例模式的实现很多中,这里展示一种最常用的实现。代码如下:
public class SingletonDemo {private static volatile SingletonDemo sInstance = null;private SingletonDemo(){}public static SingletonDemo getInstance(){if(sInstance == null){synchronized (SingletonDemo.class){if(sInstance == null){sInstance = new SingletonDemo();}}}return sInstance;}public void  printSomething(){System.out.println("this is a singleton");}
}

这种写法的好处有以下几点:

  • 构造函数 private,不能直接 new 对象,保证通过 getInstance 方法来创建
  • 由于不能直接 new 对象,所以 getInstance 方法必须是一个 static 方法;而静态方法不能访问非静态成员变量,所以这个实例变量也必须是 static 的
  • 双重检查锁,使用volatile关键字,重排序被禁止,所有的写操作都将发生在读操作之前;适合于一写多读的场景(即一个线程进行写操作,多个线程进行读操作)
//使用静态内部类的方式实现
public class Singleton{private Singleton(){}public static Singleton getInstance(){return SingletonHolder.sInstance;}private static class SingletonHolder{//该类之所以是static是因为sInstance是静态的,如果不设为静态会报错private static final Singleton sInstance=new Singleton();//重点在于确定是哪个类的单例}public void printSomething(){System.out.println("this is a singleton");}
}

策略模式

定义: 策略模式定义了一系列算法,并将每一个算法封装起来,而且使他们可以相互替换,策略模式让算法独立于使用的客户而独立改变

最常见的就是关于出行旅游的策略模式,出行方式有很多种,自行车,汽车,飞机,火车等,如果不使用任何模式,代码是这样子的

publicclassTravelStrategy{enumStrategy{WALK,PLANE,SUBWAY}privateStrategystrategy;publicTravelStrategy(Strategystrategy){this.strategy=strategy;}publicvoidtravel(){if(strategy==Strategy.WALK){print("walk");}elseif(strategy==Strategy.PLANE){print("plane");}elseif(strategy==Strategy.SUBWAY){print("subway");}}publicvoidprint(Stringstr){System.out.println("出行旅游的方式为:"+str);}publicstaticvoidmain(String[]args){TravelStrategywalk=newTravelStrategy(Strategy.WALK);walk.travel();TravelStrategyplane=newTravelStrategy(Strategy.PLANE);plane.travel();TravelStrategysubway=newTravelStrategy(Strategy.SUBWAY);subway.travel();}

很明显,如果需要增加出行方式就需要在增加新的 else if 语句,那么如何用策略模式来解决这个问题

首先,定义一个策略的接口

publicinterfaceStrategy{voidtravel();}

然后根据不同的出行方法来实现该接口

publicclassWalkStrategyimplementsStrategy{@Overridepublicvoidtravel(){System.out.println("walk");}}publicclassPlaneStrategyimplementsStrategy{@Overridepublicvoidtravel(){System.out.println("plane");}}publicclassSubwayStrategyimplementsStrategy{@Overridepublicvoidtravel(){System.out.println("subway");}

此外还需要一个包装策略的类,来调用策略中的接口

publicclassTravelContext{Strategystrategy;publicStrategygetStrategy(){returnstrategy;}publicvoidsetStrategy(Strategystrategy){this.strategy=strategy;}publicvoidtravel(){if(strategy!=null){strategy.travel();}}

测试一下代码:

publicclassMain{publicstaticvoidmain(String[]args){TravelContexttravelContext=newTravelContext();travelContext.setStrategy(newPlaneStrategy());travelContext.travel();travelContext.setStrategy(newWalkStrategy());travelContext.travel();travelContext.setStrategy(newSubwayStrategy());travelContext.travel();}}

以后如果再增加什么别的出行方式,就再继承策略接口即可,完全不需要修改现有的类

策略模式的优点

  • 定义一系列算法: 策略模式的功能就是定义一系列算法,实现让这些算法可以相互替换;所以会为这一系列算法定义公共的接口,以约束一系列算法要实现的功能;如果这一系列算法具有公共功能,可以把策略接口实现成为抽象类,把这些公共功能实现到父类里面
  • 避免多重条件语句: 根据前面的示例会发现,策略模式的一系列策略算法是平等的,可以互换的,写在一起就是通过 if-else 结构来组织,如果此时具体的算法实现里面又有条件语句,就构成了多重条件语句,使用策略模式能避免这样的多重条件语句
  • 更好的扩展性: 在策略模式中扩展新的策略实现非常容易,只要增加新的策略实现类,然后在选择使用策略的地方选择使用这个新的策略实现就好了

策略模式的缺点

  • 客户必须了解每种策略的不同: 比如让客户端来选择具体使用哪一个策略,这就可能会让客户需要了解所有的策略,还要了解各种策略的功能和不同,这样才能做出正确的选择,而且这样也暴露了策略的具体实现
  • 增加了对象数目: 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观
  • 只适合扁平的算法结构: 策略模式的一系列算法地位是平等的,是可以相互替换的,事实上构成了一个扁平的算法结构,也就是在一个策略接口下,有多个平等的策略算法,就相当于兄弟算法;而且在运行时刻只有一个算法被使用,这就限制了算法使用的层级,使用的时候不能嵌套使用

小结

以上就是对 Android 开发中常用的装饰者模式、单例模式、策略模式的认识;有需要了解更多设计模式的小伙伴,可以私信发送 “进阶” 即可 免费领取一份 Android 全套进阶技术知识学习文档+大厂面试真题及答案解析 PDF 文档,助你更快的掌握 Android 相关的技术知识

内容展示如下:

架构设计必入技能详解

由于篇幅原因,资料就不完全展示了,以上的资料保证100%免费最后大家如果觉得手册内容有用的话,可以点赞分享一下哦~

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

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

相关文章

中断系统:外部中断

中断系统:外部中断 实现功能 按下独立按键Key3,LED流水灯向右;按下Key4,LED流水灯向左。 单片机型号:STC89C52 硬件原理 中断系统就是当系统在进行一项工作时,需要终止这项工作,转而去执行另一…

Springboot复习

本笔记来自b站尚硅谷 文章目录SpringbootHelloWorld原理Value获取值和ConfigurationProperties获取值比较PropertySource 和 ImportResourceprofile自动配置原理整合日志指定配置全面接管SpringMVC启动流程自定义starterdev-toolsyml提示指标监控Springboot HelloWorld原理 配置…

Python函数练习题:通讯录管理程序实战案例

嗨害大家好鸭!我是小熊猫❤ 好久没有整实战案例类文章辽 今天就来整一整~ 功能简介 实现一个通讯录管理程序,使用函数来实现程序,采用模块化的程序设计方法: 划分通讯录程序的功能模块,使用函数实现相应的功能首先…

数据湖-hudi概述

前言 数据湖是目前比较热的一个概念,许多企业都在构建或者计划构建自己的数据湖。 数据湖是一个集中式存储库,允许您以任意规模存储所有结构化和非结构化数据。您可以按原样存储数据(无需先对数据进行结构化处理),并运…

nginx80转443

多了一个server,做了一个301的跳转 server { listen 80; server_name www.web1.com web1.com; (这里是可写别名的,第二个是别名) return 301 https://www.web1.com$request_uri; (当别人访问80,让它转到…

智能网联-浅谈基于PKI的车联网应用服务安全

智能网联-浅谈基于PKI的车联网应用服务安全 面对车联网快速发展趋势,信息安全是一项必要的防护措施。车端应用数字证书可认证合法身份,保障数据加密通信,防止信息的泄露与攻击。基于PKI的车联网应用服务安全认证体系框架,从国家层…

Java多线程的创建与Thread类的方法及使用

Java多线程的创建与Thread类的方法及使用🍎一.Thread类的属性与方法🍇1.1什么是线程🍇1.2Thread类的基础常见的构造方法🍇1.3Thread的常见属性🍇1.4Thread类常用的基础方法🍎二.Java线程的创建&#x1f347…

6步搭建一个飞机大战游戏

摘要:本文以华为云软件开发平台DevCloud为例,展示飞机大战游戏开发的DevOps实践流程。DevOps实践 DevOps实践是一种开发、测试运维一体化的模式,其实践的外在表现一般包括了如代码仓库、构建、测试、发布、配置、监控等工具形成的一个完整的…

引擎之旅 Chapter.3 文件系统

文章目录引言在此之前...Unicode和ASCIIC风格字符串的操作函数集合字符串操作字符串类型转换Part1:操作文件名和文件路径Part2:单个文件的读写文件打开的模式TFile的定义Part3:异步文件I/O异步I/O线程文件类中的异步方法引言 为什么会将文件…

数据中台开源解决方案(一)

数据中台商业的解决方案有很多,开源框架种类繁多,每一个模块都有很多开源的套件。以查询引擎为例,可以使用的开源工具有MySQL、Redis、Impala、MongoDB、PgSQL等。可以根据实际业务需要,选择合适的开源套件。 可供选择的解决方案太多,重点推荐开源解决方案,框架图如下图所…

【RCJ-2 AC220V 0.015A静态冲击继电器】

系列型号 RCJ-2/48VDC冲击继电器 RCJ-2/110VDC冲击继电器 RCJ-2/220VDC冲击继电器 RCJ-2/100VAC冲击继电器 RCJ-2/127VAC冲击继电器 RCJ-2/220VAC冲击继电器 RCJ-3/220VAC冲击继电器 RCJ-3/127VAC冲击继电器 RCJ-3/100VAC冲击继电器 RCJ-3/220VDC冲击继电器 RCJ-3/110VDC冲击继…

【论文笔记】CIKM‘22 & Amazon | (Navip) 推荐系统中图神经网络的去偏邻域聚合

目录1. Introduction2. Related Work2.1 基于GNN的推荐2.2 逆倾向评分IPS3. 模型3.1 Navip4. 实验结果本文是亚马逊在CIKM 2022的一篇工作 论文地址:https://arxiv.org/pdf/2208.08847.pdf 问题 图形神经网络(GNN)对于曝光偏差的脆弱性导致模型偏差,产生…

09-Pytorch中的序列化容器

目录 1.梯度消失和梯度爆炸 1.1 梯度消失 1.2 梯度爆炸 1.3 解决梯度消失或梯度爆炸的经验 2.nn.Sequential 3.nn.BatchNorm1d 4.nn.Dropout 1.梯度消失和梯度爆炸 在使用pytorch中的序列化容器之前,我们先来了解一下常见的梯度消失和梯度爆炸的问题。 1.1 …

②、HTML 元素学习

HTML 元素 HTML 文档由 HTML 元素定义。 HTML 元素 *开始标签常被称为起始标签(opening tag),结束标签常称为闭合标签(closing tag)。 HTML 元素语法 HTML 元素以开始标签起始HTML 元素以结束标签终止元素的内容是开始…

Class02

Class02 1.自动类型值转换 隐式类型转换 显式类型转换 隐式类型转换(自动类型转换) 隐式类型转换是小范围向大范围转换 实际上小范围包含在大范围内 整数类型的默认类型为int 浮点数类型的默认类型为double 显式类型转换(强制类型转换&am…

linux 预读机制 (linux4.14)

一、基本概念 设计背景 文件一般是顺序访问的,访问[A, B]范围的数据后,接下来很可能访问[B1, BN]数据。由于访问磁盘、flash等存储器件比较耗时,在访问 [A, B]的时候,如果提前把[B1, BN]数据从存储器件读取到ram中,那…

TTN服务器LoRaWAN网关配置流程

在LoRaWAN物联网网络中,LoRaWAN网关起到了绝对核心的作用,它在整个网络中像是一座桥梁建立起网络服务器与终端节点的通信,下面我们将简单介绍如何使用E890-470LG11网关实现TTN服务器与终端节点的通信。 首先,在LoRaWAN通信中&…

亿佰特LoRaWAN入网TTN并订阅MQTT消息

一、LoRaWAN节点入网 1.注册并登录TTN账号。 2.添加网关。Gateway EUI可自定义。 3.切换到亿百特网关配置网页(http://192.168.10.1/),配置网关。 4.切抱TTN网页,创建app,Application ID可任意取,只要不重复就行&…

MSRN(多尺度超分辨率重建)

目前的研究倾向于使用更深层次的卷积神经网络来提高性能。然而,盲目增加网络深度不能有效改善网络。更糟糕的是,随着网络深度的增加,训练过程中出现了更多的问题,需要更多的训练技巧。在本文中,我们提出了一种新颖的多…

TRC丨艾美捷TRC 1-Hexyl-2-phenyl-4说明书

1-Alkyl-2-aryl-4-(1-naphthoyl)pyrroles 作为大丨麻素 CB1 和 CB2 受体的高亲和力配体。 艾美捷TRC 1-Hexyl-2-phenyl-4化学性质: 目录号H297400 化学名称1-Hexyl-2-phenyl-4-(1-naphthoyl)pyrrole JWH-147 同义词JWH-147;(1-己基-5-苯基-1H-吡咯-3-基…