灵山招聘网灵山英才网做灵山专业的招聘网站,新媒体营销和网络营销,自己免费制作app平台,网站建设先做前台还是后台前面三篇我们通过从一些零散的例子#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧#xff0c;从现在开始正式进入设计模式介绍#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结#xff0c;和描述具体意义。
设计模式体…前面三篇我们通过从一些零散的例子和简单应用来模糊的感受了下设计模式在编程中的智慧从现在开始正式进入设计模式介绍本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结和描述具体意义。
设计模式体系结构图 七大原则
开闭原则OCPOpen Close Principle
官方解释对扩展开放软件实体应当对修改关闭(Software entities should be open for extension,but closed for modification 白话解读合成复用原则、里氏替换原则相辅相成都是开闭原则的具体实现规范 就是有新的业务的时候尽可能扩展展新类而不是修改旧类实际开发的时候大家基本上都会这么做这样对之前的业务影响比较小所以很多原则设计模式就贯穿在日常开发中。 里氏替换原则LSPLiskov Substitution Principle
官方解释继承必须确保超类所拥有的性质在子类中仍然成立(Inheritance should ensure that anyproperty proved about supertypeobjects also holds for subtype objects)
是不是完全看不明白俺也一样。
大白话其实就是当我们需要开发功能的时候尽量通过继承父类扩展父类功能的而不是直接在原本的父类上修改。 依赖倒置原则DIPDependence Inversion Principle
官方定义高层模块不应该依赖低层模块两者都应该依赖其抽象抽象不应该依赖细节细节应该以来抽象High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions
大白话面向接口编程而不是面向类编程
例如Controller里注入的是service接口而不是ServiceImpl这样Controller就不用关心servcieImpl到底依赖的那些dao同理可以推广的ServiceImpl依赖的是dao接口而不用关心具体实现。 单一原则SRPSingle Responsibility Principle
官方定义一个类应该有且仅有一个引起他变化的原因否则这个类应该被拆分There should never be more than one reason for a class to change
大白话每个类只负责自己领域类的事情而不是一篮子事情当然要注意不是一个类只有一个方法。
例如FileService可以处理文件上传下载方法但是注册登陆等方法就不该放入该类中 接口隔离原则ISPInterface Segregation Principle
官方定义一个类对另一个类的依赖应该建立在最小的接口上The dependency of one class to another on should depend on the smallest possible interface
大白话类应该建立自己专用的接口而不是建立一个万能接口。
其实这个可以配合上面两个看如果建立的万能接口同时又要满足上面依赖倒置原则那必定实现不了单一原则。 合成复用原则CRPComposite Reuse Principle
由叫组合/聚合复用原则Composition/Aggregate Reuse PrincipleCARP
软件复用时要尽量先使用组合或者聚合等关联关系实现其次才考虑使用继承关系实现。
大白话优先是用组合而不是继承这个是通用原则了主要还是继承扩展起来没那么方便。 迪米特法则LODLaw of Demeter
低耦合高内聚。
最少知识原则(Least Knowledge Principle,.LKP) 只与你的直接朋友交谈不跟“陌生人”说话 TaIk only to your immediate friends and not to strangers) 其实就是引入一个中间者来进行交互Controller层不直接和Dao层直接交互
设计模式与组件生命周期关系图 以Java为例通常我们会以结构型设计模式去构建类的类信息通过创建型设计模式去创建对象通过行为模式去控制对象的行为。
23种设计模式概述
前面三篇文章基本上都多少涉及到了一点这里咱们做个简单归纳的归纳总结后面咱们咱们会一个一个的拆分。
结构型设计模式
外观模式Facade
为子系统中的一组接口提供一个一致的界面Facade模式定义了一个高层接口这个接口使得这一子系统更加容易使用。
例子在一个电商系统中处理订单可能涉及多个子系统如支付系统、库存系统、物流系统等。外观模式可以提供一个统一的接口来处理订单从而简化客户端的调用。 适配器模式Adapter
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
例子MyBatis中的ResultSetHandler将JDBC的结果集转换为自定义的对象类型。这个过程就是适配器模式的应用将不兼容的接口进行适配。 桥接模式Bridge
将抽象部分与它的实现部分分离使它们都可以独立地变化。
例子Spring的JdbcTemplate和各种具体的数据库实现之间的分离。JdbcTemplate提供抽象操作而具体的数据库操作由不同的DataSource实现二者可以独立变化。
组合模式Composite
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。
例子在一个文件系统中文件和文件夹都可以视为节点。文件夹可以包含文件和其他文件夹这形成了一个树形结构。组合模式使得文件和文件夹的操作一致。这个例子可能有过文件处理系统的小伙伴可能才好理解再举一个列子一个管理系统他的菜单树结构的子与父结构相同这样是不是就好理解了一级菜单二级菜单嘛无限套娃就行。 装饰模式Decorator
动态地给一个对象添加一些额外的职责。就扩展功能而言Decorator模式比生成子类更为灵活。
例子在一个图形编辑器中可以对图形对象添加不同的装饰如边框、阴影。装饰模式可以动态地添加这些装饰而不需要改变图形对象的类。 享元模式 Flyweight
运用共享技术有效地支持大量细粒度的对象。 例子在一个文字处理系统中每个字符都是一个对象。如果每个字符都单独存储会占用大量内存。享元模式通过共享相同的字符对象减少内存的使用。
代理模式Proxy
其他对象提供一种代理以控制对这个对象的访问。
例子在一个远程服务调用系统中客户端通过代理对象来访问远程服务。代理对象处理与远程服务的通信和数据传输客户端只需调用代理对象的接口。SpringCloud种的Open Feign就是这个思想呢当然代理我们一般分为静态代理和动态代理但是现在很多时候静态代理和装饰器思想很接近所以很多时候代理模式指的是动态代理而java实现动态代理由离不开jdk或cglib详细讨论的时候这一块将是重点。同样提到这里咱们就不得再提一下Spring种的Aop咯。
Spring的AOP也是代理模式的一个典型应用。通过创建代理对象Spring AOP可以在方法调用前后添加额外的逻辑如事务管理、权限检查等。
MyBatis也使用代理模式生成Mapper接口的实现类调用实际的SQL操作。这个在框架中使用特别多后面一定要好好说说。 创建型设计模式
创建模式主要的关注点是怎样将对象创建出来将对象创建与使用进行剥离。像Spring框架就是依赖创建型设计模式将我们开发者从对象的创建给剥离出来对象的创建全部交给Spring托管咱们安心写自己业务代码方法的调用即可。 单例模式Singleton Pattern
单例模式在系统里你要判断一下如果有一些类只需要一个实例对象就可以了那就给那个类做成单例的模式关键点就是构造方法私有化Spring中的Bean对象默认都是单例的后面在介绍具体的设计模式的时候在详细看代码。
简单工厂模式
工厂模式的核心思想其实就是不要自己在代码里手动new一个实现类对象出来因为那样的话调用方就不是面向接口编程了你还得自己去实现了。所以一般都是用工厂的思想来提供所有实现类实例然后调用方面向接口来编程即可接口不变调用方代码不用变。
现在基本上很少去自己实现工厂模式了因为有Spring框架Spring的容器其实本质上就是个大工厂的概念将你需要的对象都放到Spring容器里需要的时候问Spirng取就完事。
工厂方法模式Factory Method
模板方法模式简单工厂模式简单工厂模式 抽象工厂模式Abstract Factory
提供一个创建一系列相关或相互依赖对象的接口而无需指定它们的具体类。在一个工厂中聚合多个同类产品的创建方法。简单理解为“工厂的工厂即可”。 建造者模式Builder
构造一个复杂的对象很多的属性有些属性构造的时候需要做一些校验格式转换
举个例子当我们销售系统收到一笔订单的时候在构建订单的时候需要对订单金额基础的校验、对产品的代码、产品类型做一些转换、供应商等。 原型模式Prototype
原型模式以某一个对象为原型然后对这个对象进行拷贝得到拷贝后的另外一个对象
例子很多BeanUtils之类的都有类似的功能后面我们在分析具体的原理和对比他们的性能等。 行为型设计模式 责任链模式Chain Of Responsibility
使多个对象都有机会处理请求从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链并沿着这条链传递请求直到有对象处理它为止。
在Spring框架中过滤器链的实现就体现了责任链模式的应用。每个过滤器负责处理请求的一部分逻辑然后将请求传递给链中的下一个过滤器。这样就形成了一条过滤器链所有的过滤器按顺序依次执行。
策略模式Strategy
可以将一系列算法把它们一个个封装起来并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。
例子在一个支付系统中支持多种支付方式如支付宝、微信、信用卡、PayPal、比特币等。每种支付方式是一个策略用户可以在支付时选择不同的支付方式。 模版方法Template Method
定义一个操作中的算法的骨架而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
例子在一个文档处理系统中可以有不同类型的文档如Word文档、PDF文档等的导出。导出的步骤大致相同打开文档、读取内容、写入目标格式、关闭文档。具体的读取和写入步骤可以由子类实现。 命令模式Command
将一个请求封装为一个对象从而使你可用不同的请求对客户进行参数化对请求排队或记录请求日志以及支持可撤销的操作。
例子在一个智能家居系统中可以有各种命令如小爱同学打开灯、关闭灯、调节温度等。每个命令可以封装为一个对象用户可以对命令进行操作如执行、撤销等。
其实对于前后端分离项目用户前端每次执行一个操作对应后端的每个请求都可以看作是一个命令的执行我们提供给前端的接口其实就是一个个封装的对象。 观察者模式Observer
定义对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都得到通知并被自动更新。
例子在一个股票交易系统中投资者可以订阅股票价格的变化。当股票价格发生变化时系统会通知所有订阅了该股票的投资者。
这个在Spring中的监听机制其实就是可以看作是一个观察者模式当模式泛化以后可以将消息中间件中的主题中的一组生产者一组消费者看作观察者模式。 访问者Visitor
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
例子在一个编译器中可以有不同的操作如语法检查、代码优化、代码生成等作用于语法树的各个节点。每个操作可以通过访问者模式实现。 状态模式State
允许对象在内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
例子在一个订单处理系统中订单可以有不同的状态如新建、已支付、已发货、已完成等。每种状态下订单的行为可能不同比如在已支付状态下可以发货但在新建状态下不可以。
这个状态模式和策略模式很想不同的是状态模式有一个自动流转的状态机通过状态的不同来实现不同的算法。 解释器模式Interpreter
给定一个语言定义它的文法的一种表示并定义一个解释器该解释器使用该表示来解释语言中的句子。
例子在一个数学表达式计算器中可以定义表达式的文法并使用解释器模式来解析和计算表达式的值。
这玩意不知道咋解释实际项目种使用的比较少之前在科技部门做个一个通用的消息触达平台定义了一些简单的占位符通过占位符规则替换一些数据应该类似解释器。
泛化到语言层面如Java 语言的Javac命令可以将Java源代码解析成Class文件抑或现在比较火的Transformer框架中的编码器与解码器将各种结构化数据解析成一组组向量后在来处理相似性问题这个似乎更满足解释器模式的概念。这个模式先放一放如果有小伙伴有比较深入的研究欢迎私信一起交流。 迭代器模式Iteration
提供一种方法顺序访问一个聚合对象中的各个元素而又不需要暴露该对象的内部表示。
例子在一个集合框架中可以有各种集合如数组、列表、集合等。迭代器模式提供了一个统一的接口来遍历这些集合中的元素。
这种Java已经有很成熟的API了咱们就不用自己去实现了设计模式一定不能为了设计而设计一定是为了解决实际问题。 中介者模式Mediator
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用从而使其耦合松散而且可以独立地改变它们之间的交互。
例子在一个聊天系统中用户之间的消息传递通过一个中介者对象如聊天服务器进行用户不需要直接知道其他用户的存在。 备忘录模式Memento
在不破坏封装性的前提下捕获一个对象的内部状态并在该对象之外保存这个状态以便以后恢复对象到先前的状态。
例子在一个文本编辑器中可以有撤销和恢复功能。编辑器可以在执行某个操作前保存当前状态以便用户需要时可以恢复到该状态。
其实Java中的序列化与反序列化可以看作是这个思想的扩展需要保留的时候序列化的文件中 设计模式带来的一些思考
1、为什么学习设计模式
其实回答这个问题的时候很多培训机构的老师或者网上资料都说设计模式是源码的基础只有学会了设计模式才能看懂源码之类的观点。
这里的观点可能不太一样设计模式也好抑或其他框架也罢都是为了我们解决实际问题而设计出来的有了设计模式的思想很多时候会给我们软件设计带来一些启发这种场景是否可以有xxx模式的思想来解决呢
其次任何一个成熟的项目都不可能由一个人来完成设计模式思想的运用可以在团队合作的时候来规范团队。举个例子在参与基金销售系统开发的时候他的交易可以各种业务如基金的认购、申购、赎回、修改分红方式等每一种业务都有对应的处理逻辑但是他们都需要和基金管理公司交互而和基金公司交互都是通过文件的形式。这样他们共同点可以抽象出来那就是文件的处理可以放到模板方法统一实现文件解析后的数据再有个各子域去实现。这样子域可以由不同的人员来开发代码风格更加统一好维护。 总结
在软件开发中设计模式不仅仅是技术上的工具更是一种思维方式和解决问题的哲学。它们通过丰富的实践和理论积累帮助开发者在面对复杂需求和变化时保持清晰的思路和高效的开发策略。无论是单例模式的实例唯一性还是策略模式的算法灵活性设计模式都在实际项目中展现出其独特的价值。通过不断学习和应用设计模式我们能够更好地理解和运用面向对象设计的原则和技巧从而打造出更加健壮和可维护的软件系统。设计模式的智慧不仅体现在代码中更融入到整个软件开发的文化与实践中成为提升团队能力和项目质量的重要支柱同样切记不能为了设计而设计目前各种语言与框架已经很成熟使用这些设计模式的时候一定要采取审慎原则。拿不定主意的时候多和公司资深前辈沟通。