设计模式(收集了知识点解密中...)
内聚:自己的东西自己保管,自己的事情自己做。
在面向对象编程中,对象自身是内聚的,是保管好自己的数据,完成好自己的操作的,而对外界呈现出自己的状态和行为。但是,没有绝对的自力更生,对外开放也是必要的!
依赖:一个对象,往往需要跟其他对象打交道,既包括获知其他对象的状态,也包括仰赖其他对象的行为,而一旦这样的事情发生时,我们便称该对象依赖于另一对象。
耦合:只要两个对象之间存在一方依赖一方的关系,那么我们就称这两个对象之间存在耦合。
耦合度:耦合的程度就是耦合度,也就是双方依赖的程度。
强耦合:妈妈和baby是强耦合。妈妈要随时关注baby的睡、醒、困、哭、尿等等状态,baby则要仰赖妈妈的喂奶、哄睡、换纸尿裤等行为,从程序的意义上说,二者互相依赖。
低耦合:你跟快递小哥之间则是弱耦合。
解耦合:从某种意义上来说,耦合天生就与自由为敌,无论是其他对象依赖于你,还是你依赖其他对象。比如有人嗜烟、酗酒,你有多依赖它们就有多不自由;因此,要想自由,就必须要降低耦合,而这个过程就叫做解耦和。
依赖倒置(Dependence Inversion Principle):解耦和最重要的原则就是依赖倒置原则;
高层模块不应该依赖底层模块,他们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
《资本论》中都曾阐释依赖倒转原则——在商品经济的萌芽时期,出现了物物交换。假设你要买一个IPhone,卖IPhone的老板让你拿一头猪跟他换,可是你并没有养猪,你只会编程。所以你找到一位养猪户,说给他做一个养猪的APP来换他一头猪,他说换猪可以,但是得用一条金项链来换——所以这里就出现了一连串的对象依赖,从而造成了严重的耦合灾难。解决这个问题的最好的办法就是,买卖双发都依赖于抽象——也就是货币——来进行交换,这样一来耦合度就大为降低了。
原则:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而非针对实现编程。
满足两个条件:
1.高层模块不应该依赖于低层模块,两个都应该依赖于抽象。
2.抽象不应该依赖细节,细节应该依赖于抽象。
在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
控制反转(Inversion of Control):控制反转跟依赖倒置是如出一辙的两个概念,当存在依赖倒置的时候往往也存在着控制反转。但是控制反转也有自己的独特内涵。比如你去下馆子,你是Client,餐馆是server。你点菜,餐馆负责做菜,程序流程的控制权属于server;而如果你去自助餐厅,程序流程的控制权就转到Client了,也就是控制反转,同时我们也将这个调用称为“回调”。
依赖注入(Dependency Injection):依赖注入,就其广义而言,即是通过“注入”的方式,来获得依赖。我们知道,A对象依赖于B对象,等价于A对象内部存在对B对象的“调用”,而前提是A对象内部拿到了B对象的引用。B对象的引用的来源无非有以下几种:A对象内部创建(无论是作为字段还是作为临时变量)、构造器注入、属性注入、方法注入。后面三种方式统称为“依赖注入”,而第一种方式我也生造了一个名词,称为“依赖内生”,二者根本的差异即在于,我所依赖的对象的创建工作是否由我自己来完成。当然,这个是广义的依赖注入的概念,而我们一般不会这样来使用。我们通常使用的,是依赖注入的狭义的概念。不过,直接陈述其定义可能会过于诘屈聱牙,我们还是从具体的例子来看。
比如OMCS网络语音视频框架,它实现了多媒体设备(麦克风、摄像头、桌面、电子白板)的采集、编码、网络传送、解码、播放(或显示)等相关的一整套流程,可以快速地开发出视频聊天系统、视频会议系统、远程医疗系统、远程教育系统、网络监控系统等等基于网络多媒体的应用系统。然而,OMCS直接支持的是通用的语音视频设备,而在某些系统中,需要使用网络摄像头或者特殊的视频采集卡作为视频源,或者其它的声音采集设备作为音频源,OMCS则提供了扩展接口——用户自己实现这个扩展的接口,然后以“依赖注入”的方式将对象实例注入到OMCS中,从而完成对音、视频设备的扩展。
接口隔离:使用多个专门的接口比使用单一的总接口要好。
原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
面向接口编程:
(why)为什么要用设计模式:合理组织代码,修改封闭,对扩展点进行扩展开放。
(where)何处使用设计模式:为了合理的利用设计模式,我们应该明白一个概念,叫做扩展点。扩展点不是天生就有的,而是设计出来的。我们设计一个软件的架构的时候,我们也要同时设计一下哪些地方以后可以改,哪些地方以后不能改。倘若你的设计不能满足现实世界的需要,那你就要重构,把有用的扩展点加进去,把没用的扩展点去除掉。这跟你用不用设计模式没关系,跟你对具体的行业的理解有关系。
设计模式的6个基本原则:
- 单一职责原则(Single Responsibility Principle)
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
单一职责原则告诉我们:一个类不能太“累”! 一个类的职责越重(这往往从构造器所需要的依赖就能体现出来),它被复用的可能性就越小。
不能否认,这个工具需要相对较高的学习成本,但是学会了依赖注入工具并理解了IOC(控制反转),DI(依赖注入)的思想之后,它将成为你开发过程中无往不胜的利器。
- 里氏代换原则(Liskov Substitution Principle)
任何基类可以出现的地方,子类一定可以出现。
里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
向上转型是Java的基础,我们经常也用到,实际上,在进行设计的时候,尽量从抽象类继承,而不是从具体类继承。同时,保证在软件系统中,把父类都替换成它的子类,程序的行为没有变化,就足够了。
- 依赖倒转原则(Dependence Inversion Principle)
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而非针对实现编程。
它的原则是:
1.高层模块不应该依赖于低层模块,两个都应该依赖于抽象。
2.抽象不应该依赖细节,细节应该依赖于抽象。
在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
- 接口隔离原则(Interface Segregation Principle)
接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
这个应该是最好理解的原则了,它的意义就是:使用多个专门的接口比使用单一的总接口要好。
- 迪米特法则,又称最少知道原则(Demeter Principle)
迪米特法则:一个软件实体应当尽可能少地与其他实体发生作用。(这个应该很好理解,就是降低各模块之间的耦合)
- 开闭原则(Open Close Principle)
一个软件应对扩展开放、对修改关闭,用head first中的话说就是:代码应该如晚霞中 的莲花一样关闭(免于改变),如晨曦中的莲花一样开放(能够扩展).
设计模式的分类:
范围 | 创建型 | 结构型 | 行为型 |
---|---|---|---|
类 | Factory Method(工厂方法) | Adapter(类) (适配器) | Interpreter(解释器) Template Method(模版方法) |
对象 | Abstract Factory(抽象工厂) Builder(建造者) Prototype(原型) Singleton(单例) |
Adapter(对象)(适配器) Bridge(桥接) Composite(组合) Decorator(装饰者) Facade(外观) Flyweight(享元) Proxy(代理) |
Chain of Responsibility(职责链) Command(命令) Iterator(迭代器) Mediator(中介者) Memento(备忘录) Observer(观察者) State(状体) Strategy(策略) Visitor(访问者) |
再细点分类:
范围 | 创建型 | 结构型 | 行为型 |
---|---|---|---|
对象创建 | Singleton(单例) Prototype(原型) Factory Method(工厂方法) Abstract Factory(抽象工厂) Builder(建造者) |
||
接口适配 | Adapter(适配器) Bridge(桥接) Facade(外观) |
||
对象去耦 | Mediator(中介者) Observer(观察者) |
||
抽象集合 | Composite(组合) | Iterator(迭代器) | |
行为扩展 | Decorator(装饰) | Visitor(访问者) Chain of Responsibility(职责链) |
|
算法封装 | Template Method(模板方法) Strategy(策略) Command |
||
性能与对象访问 | Flyweight(享元) Proxy(代理) |
||
对象状态 | Memento(备忘录) State(状态) |
||
其它 | Interpreter(解释器) |
创建型模式的理解:与对象(类)的创建有关。
结构型模式的理解:通过将不同类或对象的组合,采用继承或者组合接口,或者组合一些对象,以实现新的功能。用一句话陈述,就是对不同职责的对象(以对象/抽象类/接口的形式)之间组合调度的实现方式。
并非所有对象的组合都是结构型模式:
实际上,并非所有对对象的组合都属于结构型模式,构型模式的意义在于,对一些对象的组合,以实现新功能的方式—— 通过运行时,通过改变组合的关系,这种灵活性产生不同的效果,这种机制,普通的对象组合是不可能实现的。
行为模式的理解:为了提高类之间的协作效率。
行为模式定义:行为模式涉及到算法和对象间职责的分配,行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻划了在运行时难以跟踪的复杂的控制流,将你的注意力从控制流转移到对象间的联系方式上来。
外观模式的定义:为子系统中的一组接口提供一个一致的界面,外观模式定义一个高层接口,这个接口使得这一子系统更容易使用。
什么是容器Facade:
什么是依赖注入AOP:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!