当前位置: 首页 > 科技观察

大神解释的很详细,这么详细的Java设计模式没有收藏,可惜了

时间:2023-03-14 12:20:43 科技观察

介绍设计模式是众多程序员总结出来的优秀实践。我曾经在刚开始写项目时学习过设计模式,并在开发过程中主动或被动地使用它们。虽然现在写代码的时候不清楚是用的是哪种设计模式,但是公认的好实践代码写得巧妙,毕竟比较清爽。重新看设计模式有几个原因:***,很多优秀的源码基本都用到了设计模式,清晰的设计模式才能更好的看源码。其次,很多中间件的设计理念也是基于设计模式,其他语言也有自己好的设计实践。对我来说,设计模式是从java开始的,而不仅仅是java。第三,有了这个规范,就可以更好的与人交流,简明扼要。很多关于设计模式原理的优秀文章和书籍都说的很清楚。我来说说我自己的经历吧。1、单一职责原则是指一个类只负责做一件事。这样就可以达到解耦的效果,代码看起来更清爽,也体现了java的封装性。还有一个原则叫迪米特定律,就是一个对象对另一个对象的了解越少越好,这也是讲解耦。2.Liskov替换原则和依赖原因原则是关于继承的。父类能做的,子类能做的,子类可以尝试依赖父类做的事情;但反过来说,父类不能依赖子类来做一些事情。体现了java的继承特性。3、接口隔离原则,接口要尽量隔离。其实写的类太多了,耦合度确实低。为了让他们能够沟通,接口用得最多。毕竟,您只需要知道要做什么、如何做以及访问那个特定的类。4、开闭原则,为修改而封闭,为扩展而开放。即代码需要具有良好的延展性,不能破坏原有的代码结构。Creator模式Creator模式就是以优雅的方式创建我们使用的类。1.简单工厂模式比较少用。有一个工厂,告诉你我想要什么,你建好了就给我。例如:2.工厂模式其实和简单工厂模式没有太大区别,就是继续拆分工厂。比如刚才EasyBallFactory是一个总工厂,我们现在拆分成SoccerFactory和BasketBallFactory分别生产足球和篮球。某个工厂可以根据需求生产不同的产品。例如,可以生产不同尺寸的足球。3、抽象工厂模式抽象工厂模式主要设计一个产品组的概念,即某个工厂生产一系列配套产品。例如,SoccerFactory在生产足球的同时,还可以生产配套的足球杂志。4.单例模式单例模式有很多种形式。最佳实践应该是双重判断,以确保只有一个是新的。单例可以说是一种很常见的设计模式。单例意味着在服务容器的生命周期中只能有一个这样的实例。比如Servlets、Spring注入的bean等都是单例。5.建造者模式创造了一个复杂的对象分布。如果一个超大类的属性太多,我们可以把属性分类,不同属性组成一个稍微小一点的类,然后再把几个小类组合起来。例如,一台计算机可以分成不同的稍小的部分CPU、主板和显示器。CPU、主板、显示器各有更多元器件,不再细分。SpringBoot实现了0配置,几乎所有的配置都是用java代码写的。大量的配置不得不让配置类采用构建器模式,这样层次结构就比较清晰了。6.原型模式原型模式使用较少,用于创建重复的对象。如果需要实现Cloneable,可以选择重写clone()方法。克隆分为浅克隆和深克隆。浅克隆只是克隆引用,对象仍然是一个。深度克隆意味着对象也是新创建的,具体如下:结构模式上面的设计模式可以帮助我们非常优雅地创建对象。让我们看看几种对象关系之间的模型。7、代理模式Spring的AOP采用了动态代理。我不知道什么是动态的。用过Spring的人都知道。看看最基本的代理模型是什么样子的。代理是一个对象,它协助另一个对象做某事,同时可以增加一点辅助功能。比如买车,确实是花钱买的车,但是不能直接找厂家谈。你应该通过4S店购买,同时4S店会帮你保险和减税,最后你才能拿到车。你想要的车。8、Adapter模式Adapter,顾名思义,就是让两个不兼容的东西一起工作。比如插座的电源是220V,手机直接给他220V50HZ的交流电。相信会直接炸掉(诺基亚除外。。。)手机充电器适配降压,将交流电转为直流电。除了这种需要改变属性的操作(说的比较简单,不举例子),接口继承中也会用到适配器。假设一个***接口有很多方法需要类去实现。我刚写了一个新类,只想选择实现一两个接口。我是否需要实现其他方法,即使是一个空实现(简单实现,没有任何逻辑操作),这就是我们需要一个适配器类来空实现那些方法。我的新类只需要继承这个适配器类。如果要实现某个方法,只需要重写配置类中对应的方法即可。这种模式基本都是用的,毕竟谁的代码没有***接口。9.桥接模式用于抽象和实现的解耦。它再次脱钩。看来设计模式就是要教我们如何优雅地解耦。提高了代码的可扩展性,可以实现代码的动态切换。原有的Ball、Soccer、BasketBall将继续使用,并增加新的类。10.Decoration模式是一个装饰类,在原有类的基础上增加了一点功能。是不是很像代理模式,我什至可以把整个代码都搬过来,还是有道理的。这两种模式的含义有点不同。代理模式是指原对象不能做某事,必须允许代理对象做。主要关注的是代理对象,例如买车。装饰模式的意思是原来的对象是直接做这个的,只是功能增强了一点,主导权在原来的对象。比如做饭的时候撒点盐。11.外观模式,也称为门面模式,即门面。一个操作不需要让对象知道其内部实现的复杂性,尽可能让用户感知的非常简单。这就是为什么我们的controller层尽量少(或者必须)少业务逻辑,让controller层只做参数传递和一般参数校验的功能,剩下的交给service。我们还需要不断将“长”的极长代码封装成代码中的一个方法,“让它处处好看”。看看我们写的代码。这里只是起到传递参数的作用。客户不必担心足球是如何制作的。12.组合??模式组合模式就是将具有某种包含关系的数据组织在一起,典型的例子就是树结构。比如菜单函数,一个菜单除了自身的属性外,还可能包含子菜单,创建的时候可以使用递归的方法。13、享元模式享元模式允许用户尽可能复用已有的对象,避免重复创建对象造成的资源浪费。首先你会想到数据库连接池和String常量池。推而广之,几乎所有与缓存相关的代码都会在一定程度上使用享元模式。享元模式要求大多数对象都可以被外部化。这里要讲两个概念。享元模式对象的属性可以分为内部状态和外部状态两部分。内部状态是指不随环境变化的值,如个人信息。外在状态是指在环境中发生变化的值,不能共享的信息,比如大学生选修的课程。行为模式创建对象,对象之间存在结构关系,因此我们需要看如何更优雅地进行交互。14、策略模式定义了一组算法,封装了每一个算法,并使它们可以互换。可以说是对一组算法的封装,根据客户给出的不同要求进行不同的操作。以这个简单的计算器为例。15.观察者模式定义了一对多的依赖关系。当一个对象(被观察者)的状态发生变化时,会通知所有依赖于该对象的观察者进行相关操作。很多中间件依赖观察者模式,比如RabbitMQ,还有那些事件驱动模型(比如node)。下面我们举个例子。被观察者为监考老师。考试时间结束后,通知所有旁听者交卷。16.责任链模式责任链模式为请求创建一个接收者对象链,将发送者和接收者解耦。过滤器链是责任链模型。17.TemplateWayPattern一个抽象类公开定义了一种方式/模板来执行它的方法。它的子类可以根据需要覆盖方法实现,但调用将以抽象类中定义的方式进行。SpringBoot给用户封装了很多继承代码,都是用模板,比如那一堆XXX模板。18.状态模式简单来说,一个对象有不同的状态,根据状态的不同可能会有不同的行为。19.迭代器模式提供了一种在不知道内部结构的情况下顺序访问对象内部元素的方法。现在很少有人自己实现迭代器了。基本上成熟的框架或者强大的JDK都会提供访问方式,比如java中的迭代器。这主要是为了进一步封装对象的内部结构,让行为和结构想要耦合。这不是一个例子。用过iterator的朋友应该知道,访问下一个元素是不停的next。20.命令模式命令模式是将请求以命令的形式包装在对象中,传递给对象。调用对象找到一个合适的处理命令的对象,将命令传递给相应的对象,由对象执行。简单的说就是将不同的请求封装到一个对象中,不同的请求调用不同的executor。21、备忘录模式相当于拍一张快照,在不破坏对象本身结构的情况下,记录对象的一个??状态,并可以在适当的时候恢复到这个状态。该方法在数据库做事务回滚时使用。这里需要注意的是,该对象并没有与备忘录本身耦合,而是与备忘录管理类(即List)耦合。这个很好理解,毕竟快照不止一个。22、访问者模式访问特定角色时,需要通过访问者访问。当一个对象不方便你直接访问时,你需要给访问者一个自己的引用,使用访问者来访问对象。例如在化学课上,如果你想看到一个细胞结构,你需要通过显微镜间接地访问它,因为肉眼无法直接看到微观世界中的事物。23、中介模式降低了对象或事物之间通信的复杂度,降低了耦合度。例如,在分布式系统中,它不是一个需要实时反馈的操作。我们不需要直接连接。我们只需要告诉中间件我们要做什么,中间件告诉另一个系统。比如在访问(用户点击)一个新闻操作时,需要记录谁访问了什么新闻,同时新闻浏览量加1,实时更新用户偏好...在简而言之,需要更新n个数据库表,甚至操作多个像ES、Mongo等中间件的数据。但是对于用户来说,我只是做了一个点击操作,希望得到的结果是看一条新闻。你操作那么多,这么慢,用户体验很差,并发也很低,所以还不如搞成两个小系统,系统A,拉消息,推送,组装一条消息抛出到MQ中间件,ok,结束,用户看到消息了。然后系统B监控,得到这个消息,进行各种更新。在这里,这个中间件是我们的中介。再比如,MVC中的控制层是表现层和模型层之间的中介。再举个例子,下面这个聊天室:24.Interpreter模式构建一个翻译方法,将某种语言或描述翻译成我们理解的语言或描述。Wellunderstanded这里的意思是可以理解和快速。本来我还想举个高级编译器,把底层语言甚至机械语言和我们使用的高级编程语言结合起来。想了想,其实Map也算得上是一个非常优秀的编译器了。key可以存一个很小的字符串,value理论上可以存任何东西,所以代码就不写了。