Java 设计模式(java design patterns)

什么是设计模式?

前辈们,在长期开发中为了解决某种重复出现的问题,经过长期的总结,代码结构优化,最终确定一套解决办法。

为什么学习设计模式?

对程序设是有帮助的,提高代码额可重用性,可扩展性,可靠性,可维护性。提高程序员编码设计模式,设计出标准化程序。

设计模式有哪些?

创建型模式:如何创建对象,单例,工厂模式

结构化模式:类与类如何组合,组织出更大的结构,代理模式

行为化模式:类与类如何协作

常用的设计模式

单例模式

在一个程序中,一个类只能创建一个对象。

实现:

1. 构造方法私有化,在其他类中就不能 new 对象

2. 在单例类中,向外界提供一个公共的静态方法获得单例对象,在类的内部就可以方便控制。

分为:

饿汉式单例:在类中关联自己,为静态,当类加载时,创建单例对象,调用方法时,直接返回即可,类只加载一次。

饿汉式单例/急切式单例 不存在线程安全问题,因为类加载的时候,对象已经创建,仅且创建一次。

public class SingleTon {private static SingleTon singleTon = new SingleTon();private SingleTon1(){}public static SingleTon getSingleTon() {return singleTon;}}

懒汉式单例:在类加载的时候不着急创建,第一次调用时创建对象,会存在线程安全问题。

public class SingleTon {private static SingleTon singleTon = null;private SingleTon(){}public static SingleTon getSingleTon() {if(singleTon == null){singleTon = new SingleTon();}return singleTon;}}

第一种:加入synchronized 关键字

加入synchronized 不建议使用,执行的效率低

public class SingleTon {private static SingleTon singleTon = null;private SingleTon(){}public static synchronized SingleTon getSingleTon() {if(singleTon == null){singleTon = new SingleTon();}return singleTon;}}

 第二种:双重检索+volatile

双重检索

双重检索:有多个线程进入后,会先判断是否为空,为空则进入第一层,当多个线程进入第一层后后,synchronized修饰的代码块,只允许一个线程进入第二层,为空,则创建一个SingleTon对象,否则,出第二层。当下一次线程进入后,singleTon为空,则重复前面操作,否则就直接返回singleTon变量。

public class SingleTon {private volatile static SingleTon singleTon = null;private SingleTon(){}public static SingleTon getSingleTon() {if(singleTon == null){synchronized(SingleTon.class){if(singleTon == null){singleTon = new SingleTon();}}}return singleTon;}
}

volatile关键字

原因:使用volatile关键字修饰可以保证可见性,有序性。 在创建一个SingleTon对象,并给引用对象赋值这个过程中底层拆分为三条指令。

第一步,new SingleTon() 的时候在内存中申请一份空间,这一步是不会发生重排的,

第二步,调用构造方法初始化对象。

第三步,将对象地址赋给引用变量。

但是在第二步和第三步进行的过程中,会发生重排,有可能将第三步重排到第二步执行, 这时候会造成引用变量执行的是一个半成品的对象

编译后的汇编指令码:

正常执行顺序 0 new #3 //new 申请内存空间

3 dup

4 invokespecial #4 : ()V> //调用构造方法

7 astore_1 //将对象地址赋给引用变量

8 return

线程 1 开始执行,先执行 new,在内存中申请内存空间

此时指令可能发生重排序,先把半成品对象引用地址赋给引用变量 

 线程 1 暂停执行,线程 2 进入到 cpu 执行,引用变量 t 不为空,指向的是半成品对象 

原因:使用volatile关键字修饰可以保证可见性,有序性

在创建一个SingleTon对象,并给引用对象赋值这个过程中底层拆分为三条指令

第一步,new SingleTon() 的时候在内存中申请一份空间,这一步是不会发生重排的,

第二步,调用构造方法初始化对象

第三步,将对象地址赋给引用变量。

但是在第二步和第三步进行的过程中,会发生重排,有可能将第三步重排到第二步执行, 这时候会造成引用变量执行的是一个半成品的对象

工厂模式

创建型模型,批量创建对象,创建对象与使用对象相分离。

简单工厂模式:创建的对象不多,只需要一个工厂类就可以完成。在简单工厂模式中创建实例的方法为静态方法。

角色:

简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。创建类的方法可以被外界直接调用,创建所需产品对象。

抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。

具体产品(ConcreteProduct):是简单工厂模式的创建目标

代理模式

场景:AOP的底层实现就是使用动态代理

代理模式设计思想

想完成某件事情,不能/不想直接去访问目标,可以通过中介来帮助你联系完成某件事情。

例如:找房子,不想直接去找房东,可以通过中介来帮助自己完成找房子这件事

代理优点可以保护目标对象,对访问者提供额外操作,将客户端与目标对象分离,一定程度上降低了系统的耦合度。

静态代理

       实际中很少使用静态代理,因为其代理类实现的接口必须与目标类实现接口一致扩展起来就比较麻烦。代理类必须实现与目标类相同的接口(目标类是必须要实现接口的),这样扩展性降低了。

动态代理

       代理类不需要实现与目标类相同的接口,这样就可以代理任意的目标类,但是是有要求的,目标类必须实现接口的此种方法。

核心就是动态性

怎样实现动态性?

      通过java的反射机制实现,动态获取目标类信息,动态生成代理对象。目标类也是必须要实现一个接口,而代理类不需要实现与目标类相同的接口,实现invocationHandler接口。

代理类不需要实现与目标类相同的接口,这样就可以代理任意的目标类。但是是有要求的,目标类必需实现接口,此种方式是动态代理的实现方式之一:

jdk代理 是一种纯反射机制实现(动态获取目标类接口方法)

步骤:

  1. 编写一个委托类的接口,即静态代理的(UserDao)
  2. 实现一个真正的委托类,即静态代理的(UserDaoImpl)
  3. 创建一个动态代理类,实现InvocationHandler 接口,并重写改invoke方法(Dtproxy)
  4. 在测试类中,生成动态代理的对象。(Test)

总结:相比于静态代理,减少了业务的工作量,降低了系统的耦合度。但是必须使用interface代理,注定有一个共同的父类叫Proxy,即目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。

代码实现

代理类:

public class Dtproxy implements InvocationHandler {Object object;//真实对象,接收任何的目标类对象public Dtproxy(Object object) {this.object = object;}/*在代理类中调用目标类中的具体方法,动态的将代理动态对象,目标类中要调用的方法,及方法中的参数传递过来Method method  就是动态获取的真正要执行的方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("之前开启事务");method.invoke(object);System.out.println("之后提交事务");return proxy;}}

UserDao接口:

public interface UserDao {void saveUser();
}

 UserDaoImpl:

public class UserDaoImpl implements UserDao{@Overridepublic void saveUser() {System.out.println("普通用户保存");}
}

 VipUserDaoImpl:

public class VipUserDaoImpl implements UserDao {@Overridepublic void saveUser() {System.out.println("vip用户保存");}
}

 Test测试

public class Test {public static void main(String[] args) {VipUserDaoImpl vip = new VipUserDaoImpl();InvocationHandler dtproxy =  new Dtproxy(vip);//自己创建的代理类对象//这才是真正的创建动态代理对象                                                         //获取目标类所实现的接口UserDao userDao =    (UserDao) Proxy.newProxyInstance(Dtproxy.class.getClassLoader(),VipUserDaoImpl.class.getInterfaces(),dtproxy);userDao.saveUser();//使用代理对象调用接口中的方法,获取当前调用的方法,最终调用invoke方法 }
}

执行结果: 

 Cglib代理

首先目标类不需要实现接口,采用动态字节码技术,可以为目标类动态的生成父类,采用方法拦截技术实现。

步骤:

  • 引入chlib的jar包
  • 在内存中动态的创建子类
  • 代理类不能用final,否则报错
  • 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法。

CGLibProxy类 

/** 动态代理类*/
public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class<?> clazz){  enhancer.setSuperclass(clazz);  enhancer.setCallback(this);  return enhancer.create();  }  /** 拦截所有目标类方法的调用 * 参数: * obj  目标实例对象 * method 目标方法的反射对象 * args 方法的参数 * proxy 代理类的实例 */  public Object intercept(Object obj, Method method, Object[] args,  MethodProxy proxy) throws Throwable {//代理类调用父类的方法  System.out.println("开始事务");  Object obj1 = proxy.invokeSuper(obj, args);  System.out.println("关闭事务");  return obj1;  }
}
public class UserDaoImpl{public void save() {System.out.println("UserDaoImpl:save()");}}
public class Test {public static void main(String[] args) {CGLibProxy proxy = new CGLibProxy();  UserDaoImpl userDaoImpl = (UserDaoImpl) proxy.getProxy(UserDaoImpl.class);userDaoImpl.save();}
}

 Cglib和jdk的优缺点

  • 使用JDK动态代理,目标类必须实现的某个接口,如果某个类没有实现接口则不能生成代理对象。
  • Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型(采用动态创建子类的方法,对final修饰的方法无法进行代理)。
  • 从执行效率上看,Cglib动态代理效率较高。

对象克隆

为什么要克隆?

因为new 出来的对象的属性还是初始化的值,而需要新的克隆的对象可能是已经修改过的对象,这是需要新的对象来保存当前对象的状态,而我们采用new 的方法,麻烦并且浪费空间,效率低,所以采用clone(),来解决,因为底层调用native方法,效率高。

为什么需要复制?

场景:    

  • 接收前端数据
  • dao封装数据   
  • 后端向前端响应数据

引用复制:把一个对象进行复制,复制出一个新的对象。

浅克隆和深克隆的区别

是否支持引用类型的成员变量的复制

浅克隆

在浅克隆中,当对象被复制是只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

实现:

  • 在 Java 语言中,通过覆盖 Object 类的 clone()方法可以实现浅克隆。
  • 在 spring 框架中提供 BeanUtils.copyProperties(source,target);

深克隆

在深克隆中,除了对象本身被复制外,对象所包含的所有的成员变量也被复制。

实现:

  • 通过覆盖 Object 类的 clone()方法 实现
  • 可以通过序列化(Serialization)等方式来实现

序列化实现深克隆:

序列化就是将对象写到流的过程,写到流的对象是对原有对象的一个拷贝,而原对象仍然存在内存中,通过序列化实现的拷贝不仅可以复制对象本身,还可以复制其引用的成员对象,所以,可以用过序列化将对象写到一个流中,再从流中将其读出来,实现深克隆。

 解决多层克隆问题

 如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用 clone 方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

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

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

相关文章

叫ChatGPT用html+css+js写一个圣诞节代码,看看什么样子?

最近ChatGPT这么火&#xff0c;那就让他给我写点代码吧。 如何注册一个账号&#xff0c;参考&#xff1a;注册ChatGPT详细指南 注册不了的小伙伴们&#xff0c;咱们评论区见&#xff0c;问一个最想问的问题&#xff0c;看到就给你回复&#xff01; 我已经注册好了&#xff0c;…

前端实现六一儿童节祝福语分享,烟花特效助您表心意

部分数据来源&#xff1a;ChatGPT <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>六一儿童节祝福</title><style>body {background-image: url(https://picsum.photos/1920/1080);backgr…

chatgpt赋能python:10个好玩的Python代码-让编程更有趣!

10个好玩的Python代码- 让编程更有趣&#xff01; 作为一名有10年Python编程经验的工程师&#xff0c;我深刻理解到编程可以是一件令人兴奋和有趣的事情。Python是流行且多才多艺的编程语言&#xff0c;具有简洁易懂的语法和丰富的库&#xff0c;可以帮助开发人员快速轻松地实…

大型语言模型与文本摘要

大型语言模型与文本摘要 基于大型语言模型的抽取式摘要基于大型语言模型的零样本跨语言摘要基于大型语言模型的问答式摘要通过摘要任务评估大型语言模型的事实一致性基于大型语言模型的摘要事实一致性评估器未来方向大型语言模型的自我偏好基于大型语言模型生成提示基于大型语言…

ChatGPT玩起来真是上头,AI广泛应用元年体验AI之美

概述 ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型&#xff0c;一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xf…

推荐一款idea神级代码插件【Bito-ChatGPT】而且免费!- 第9篇

历史文章&#xff08;文章累计460&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 文…

ChatGPT - 获取简短的书籍摘要的Prompt

文章目录 Prompt例子 Prompt “总结[书籍名称]&#xff0c;并给我列出最重要的学习和观点。”例子

小米AX6000开启SSH后的高级用法

买的是RA72版本的AX6000,售价599,高通的CPU。 看看高颜值和唬人的外观,图示如下: 关于AX6000开启SSH的方法有很多介绍的,这里关键讲几点: 先升级RA72对应的固件,降级到41版本。 附上:miwifi_ra72_firmware_59812_1.0.41.bin 版本固件地址: http://cdn.cnbj1.fds.a…

为什么我觉得这次的chatGPT是真的智能AI

写在前面 openAI在2022年11月推出了chatGPT&#xff08;全称Chat Generative Pre-trained Transformer【聊天生成型預訓練變換模型】维基百科&#xff09;说的直白一点就是一个目前为止&#xff0c;这个星球上可以见到的最智能的机器人&#xff0c;他可以完成一些人类认知范围内…

第四届中国计算机教育大会“人工智能与大模型论坛”将于4月22日厦门召开

2023 年 ChatGPT 全球爆红&#xff0c;瞬间在国内引起了对大语言模型的热议。全球头部科技大厂再次站上了同一个赛道&#xff0c;很多 AI 领域的创业者、创投机构行动了起来&#xff0c;开启了大语言模型“军备竞赛”。人工智能与大模型技术的发展&#xff0c;离不开高校与产业…

chatgpt赋能python:Python培训:成为一名高薪Python工程师

Python培训&#xff1a;成为一名高薪Python工程师 Python已成为当今最流行的编程语言之一&#xff0c;它广泛应用于人工智能、机器学习、数据科学和Web开发等各个领域。许多公司都在寻找经验丰富的Python工程师来开发他们的产品。如果你想成为一名高薪Python工程师&#xff0c…

记一次和ChatGPT一起排查线上问题

某日现场技术支持找到了我&#xff0c;问我有个数据上报的功能&#xff0c;记录的都是上报失败&#xff0c;让我排查一下。我第一印象当然是甩锅&#xff0c;啊不对问一下情况&#xff0c;准备排查问题。 先交代一下基础情况&#xff1a;功能就是我们将我们系统的数据上报到对方…

AI 2.0时代,再看消费物联网十年

本文是「光锥智能」的「十年系列」之二&#xff0c;对前沿科技影响千行百业数字化和智能化的复盘和展望&#xff0c;第一篇《中国芯片投资十年》获得了业界科技、财经、创投和芯片垂类媒体的广泛关注。 【划重点】 从消费互联网、移动互联网到万物智联&#xff0c;正是一个“…

月薪13K!国企小哥抛弃“铁饭碗”转行测试,亲身经历告诉你选高薪or稳定

对于很多程序员来说&#xff0c;国企or大厂一直都是一个两难的抉择&#xff0c;该选择稳定还是高薪&#xff0c;许多小伙伴都在这个问题犯了难。 可他却用自己的努力和实际行动做出了最好的选择&#xff0c;为自己的职业道路画上了浓墨重彩的一笔。 话不多说&#xff0c;一起…

36张图,一次性补全网络基础知识

点击上方 前端Q&#xff0c;关注公众号 回复加群&#xff0c;加入前端Q技术交流群 转自&#xff1a;网络工程师笔记 OSI和TCP/IP是很基础但又非常重要的知识&#xff0c;很多知识点都是以它们为基础去串联的&#xff0c;作为底层&#xff0c;掌握得越透彻&#xff0c;理解上层时…

基于LLM的生成式AI正在快速变革RPA人机交互

如果问RPA对程序开发以及自动化有哪些贡献&#xff0c;其中一个答案便是它改变了人机交互&#xff08;HCI&#xff0c;human-computer interaction&#xff09;。 在传统工作流自动化工具中&#xff0c;软件开发人员不得不生成一个操作列表&#xff0c;使用内部应用程序编程接…

大模型时代来临,基于LLM的生成式AI正在快速变革RPA人机交互

从“人RPA”到“人生成式AIRPA”&#xff0c;LLM如何影响RPA人机交互&#xff1f;换个角度&#xff0c;从人机交互看LLM如何影响RPA影响程序开发与流程自动化人机交互的RPA&#xff0c;现在也要被LLM改变了LLM如何影响人机交互&#xff1f;生成式AI怎么改变RPA人机交互&#xf…

马斯克开造人形AI 变形金刚要成真?

当5个人形机器人迎面走来&#xff0c;你会下意识地期待它们具备怎样的能力。特斯拉最近公布的视频给出答案&#xff0c;它自研的机器人“擎天柱”&#xff08;Optimus&#xff09;能够探索环境&#xff0c;复刻人类动作&#xff0c;自主操纵物品。 特斯拉CEO埃隆马斯克对这些与…

chatgpt大模型赋能人形机器人之我见

我个人的看法&#xff08;不涉及任何和他项目相关的细节或商业机密&#xff0c;仅仅是我个人的泛泛而谈&#xff09;&#xff1a; 1、从大趋势来说&#xff0c;人形机器人的灵活度和通用性确实非常的高&#xff0c;是有前景的。另外轮式足式也不是他独一例&#xff0c;像 ETH …

Python吞噬世界,GPT吞噬Python!ChatGPT 上线最强应用:分析数据、生成代码都精通

当地时间 7 月 7 日&#xff0c;OpenAI 在社交平台表示&#xff0c;将向所有 ChatGPT Plus 用户开放代码解析器&#xff08;Code Interpreter&#xff09;功能。消息一出便瞬间引发了开发者们的广泛关注&#xff0c;该功能被有的开发者认为是自 OpenAI 发布 GPT-4 以来最强大的…