大家好,又见面了,我是全栈君。
面向对象设计原则
- 单一职责原则 Single Responsibility Principle
- 从软件变化的角度来看。就一个类而言,应该仅有一个让他发生变化的原因。
- 正确抽象是实现SRP的关键
- 开闭原则 Open-Closed Principle
- 软件实体(类、模块、函数等等)应该是能够扩展的,可是不可改动的
- 开闭原则是面向对象设计的核心,抽象是OCP的核心
- 总有一些功能不能通过扩展来实现须要改动源码。不要over-consider OCP
- 里氏替换原则 Liskov Substitution Principle
- 在不论什么父类出现的地方都能够用其子类替代。
同一个继承体系中的对象应该有共同的行为特征。
- 继承关系(IS-A)是基于对象的行为而非其概念,行为依赖于上下文和详细场景
- LSP样例:java.util.Properties is a java.util.Hashtable
- LSP是理论的并且严格的,有时候实际不能全然满足LSP是能够接受的
- 在不论什么父类出现的地方都能够用其子类替代。
- 依赖注入原则 Dependence Inversion Principle
- 高层模块不应该依赖于低层模决,二者都应该依赖于抽象。
- 进一步的,抽象不应该依赖于细节,细节应该依赖于抽象。
- 针对接口编程。不要对实现编程
- 接口分离原则 Interface Segregation Principle
- 接口应该是原子的、高内聚扮演独立的角色或提供独立的角色。
- ISP能够看做是SRP在接口中的描写叙述。
- 迪米特法则 Law Of Demeter
- 一个对象应当对其它对象尽可能少的了解。仅仅和直接依赖的对象通信减少各个对象之间的耦合,提高系统的可维护性
- 组合/聚合复用原则 Composite/Aggregate Reuse Principle
- 在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分。新的对象通过向这些对象的委派达到复用已有功能的目的。
- 组合是黑盒复用,包括对象的细节对于客户是不可见的。
- 继承是白盒复用,强耦合,代码是静态的被复用。
- 继承破坏了封装,父类的细节暴露给了子类。
- 继承的实现是静态的,执行时候不能改变,缺乏灵活性。
设计模式
- Creational Patterns 创建型(与对象创建相关)
- Factory Method 工厂方法 (类模式)
- Abstract Factory 抽象工厂
- Singleton 单例
- Builder 创建
- Prototype 原型
- Structural Patterns 结构型(处理类或对象的组合)
- Adapter 适配器 (类或对象模式)
- Decorator 装饰器
- Composite 合成
- Facade 外观
- Flyweight 享元
- Proxy 代理
- Bridge 桥梁
- Behavioral Patterns 行为型(对类或对象如何交互和怎么分配职责进行描写叙述)
- Interpreter 解释器 (类模式)
- Template Method 模板方法 (类模式)
- Chain of Responsibility 责任链
- Command 命令
- Iterator 迭代器
- Mediator 调停者
- Memento 备忘录
- Observer 观察者
- State 状态
- Strategy 策略
- Visitor 訪问者模式
类模式处理类和子类之间的关系,这些关系通过继承建立。是静态的,在编译时刻便确定下来了。
对象模式处理对象之间的关系。这些关系在执行时刻是能够变化的。更具动态性。
从某种意义上来说,差点儿全部模式都使用了继承,所以这里类模式仅仅指那些集中处理类之间关系的 模式,而大部分模式都属于对象模式。
- 创建型类模式将对象的部分创建工作延迟到子类(工厂方法),而创建型对象模式则将它延迟到还有一个对象中。
- 结构型类模式使用继承机制来组合类(类适配器)。而结构型对象模式则描写叙述了对象的组装方式。
- 行为模式使用继承描写叙述算法和控制流(模板方法,解释器),而行为对象模式则描写叙述一组对象如何协作完毕单个对象所无法完毕的任务。
有些模式经常绑定一起使用,如Composite常和Iterator或Visitor一起使用。有些模式是可替换的Prototype经常使用来替换Abstract Factory;有些模式虽然使用意图不同。但产生的设计结果是非常相似的。如Composite和Decorator的结构图相似的。
能够依据模式的“相关模式”部分所描写叙述的它们如何互相引用来组织设计模式,来进一步理解各种设计模式。
设计模式解决设计问题
- 寻找合适的对象
- 设计模式帮你确定并不明显的抽象和描写叙述这些抽象的对象。描写叙述过程或算法的对象现实中并不存在,但它们却是设计的关键部分
- Strategy模式描写叙述了如何实现可互换的算法族。
- State模式将实体的每个状态描写叙述为一个对象。
- 决定对象的粒度
- Facade模式描写叙述了如何用对象表示完整的子系统。Flyweight模式描写叙述了如何支持大量的最小粒度的对象。
- 其它一些设计模式描写叙述了将一个对象分解成很多小对象的特定方法。
Abstract Factory和Builder产生那些专门负责生成其它对象的对象。
- Visitor和Command生成的对象专门负责实现对其它对象或对象组的请求。
- 指定对象的接口
- 设计模式通过确定接口的主要组成成分及经接口发送的数据类型,来帮助你定义接口。设计模式或许还会告诉你接口中不应包含哪些东西。
- 设计模式也指定了接口之间的关系。Decorator和Proxy模式要求Decorator和Proxy对象的接口与被修饰的对象和受托付的对象一致。
- Visitor模式中,Visitor接口必须反映出Visitor能訪问的对象的全部类。
- 设计应支持变化。获得最大限度复用的关键在于对新需求和已有需求发生变化时的预见性。要求你的系统设计要可以对应地改进。一些导致又一次设计的一般原因。以及解决这些问题的设计模式 例如以下:
- 通过显式地指定一个类来创建对象。在创建对象时指定类名将使你受特定实现的约束而不是特定接口的约束。
- 设计模式:Abstract Factory, Factory Method, Prototype
- 对特殊操作的依赖。当你为请求指定一个特殊的操作时,完毕该请求的方式就固定下来了。
为避免把请求代码写死,你将能够在编译时刻或执行时刻非常方便地改变响应请求的方法。
- 设计模式:Chain of Responsibility, Command
- 对硬件或软件平台的依赖。外部的操作系统接口和应用编程接口API在不同的软硬件平台上是不同的。
- 设计模式:Abstract Factory, Bridge
- 对对象表示或实现的依赖。知道对象如何表示、保存、定位或实现的客户在对象发生变化时可能也须要变化。对客户隐藏这些信息能阻止连锁变化。
- 设计模式:Abstract Factory, Bridge, Memento, Proxy
- 算法依赖算法。在开发和复用时经常被扩展、优化和替代。依赖于某个特定算法的对象在算法发生变化时不得不变化。
- 设计模式:Builder, Iterator, Strategy, Template Method, Visitor
- 紧耦合。紧耦合的类非常难独立地被复用。由于它们是互相依赖的。松散耦合提高了一个类本身被复用的可能性。而且系统更易于学习、移植、改动和扩展。设计模式使用抽象耦合和分层技术来提高系统的松散耦合性。
- 设计模式:Abstract Factory, Command, Facade, Mediator, Observer, Chain of Responsibility
- 通过生成子类来扩充功能。
通常非常难通过定义子类来定制对象。
每个新类都有固定的实现开销(初始化、终止处理等)。定义子类还须要对父类有深入的了解。
一般的对象组合技术和详细的托付技术,是继承之外组合对象行为的还有一种灵活方法。过多使用对象组合会使设计难于理解。很多设计模式产生的设计中。你能够定义一个子类,且将它的实例和已存在实例进行组合来引入定制的功能。
- 设计模式:Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy
- 不能方便地对类进行改动。有时你不得不改变一个难以改动的类(可能没有源码或者可能会改变其已存在子类)
- 设计模式:Adapter, Decorator, Visitor
- 通过显式地指定一个类来创建对象。在创建对象时指定类名将使你受特定实现的约束而不是特定接口的约束。
选择设计模式
- 考虑设计模式是如何解决设计问题的
- 浏览模式的意图部分
- 研究模式如何互相关联
- 研究目的相似的模式
- 检查又一次设计的原因
- 考虑你的设计中哪些是可变的。
考虑你想要什么变化却又不会引起又一次设计。
最基本的一点是封装变化的概念,这是很多设计模式的主题。下表列出了设计模式同意你独立变化的方面。你能够改变它们而又不会导致又一次设计。
设计模式 | 意图 | 可变的方面 |
---|---|---|
Abstract Factory | 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们详细的类。 | 对产品对象家族 |
Builder | 将一个复杂对象的构建与它的表示分离。使得相同的构建过程能够创建不同的表示。 | 怎样创建一个组合对象 |
Factory Method | 定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
Factory Method使一个类的实例化延迟到其子类。 |
被实例化的子类 |
Prototype | 用原型实例指定创建对象的种类,而且通过拷贝这个原型来创建新的对象。 | 被实例化的类 |
Singleton | 保证一个类仅有一个实例,并提供一个訪问它的全局訪问点。 | 一个类的唯一实例 |
Adapter | 将一个类的接口转换成客户希望的另外一个接口。
Adapter模式使得原本因为接口不兼容而不能一起工作的那些类能够一起工作。 |
对象的接口 |
Bridge | 将一个复杂对象的构建与它的表示分离,使它们都能够独立地变化。 | 对象的实现 |
Composite | 将对象组合成树形结构以表示“部分-总体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。 | 对一个对象的结构和组成 |
Decorator | 动态地给一个对象加入一些额外的职责。
就扩展功能而言。Decorator模式比生成子类方式更为灵活。 |
对对象的职责。不生成子类 |
Facade | 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加easy使用。 | 对一个子系统的接口 |
Flyweight | 运用共享技术有效地支持大量细粒度的对象。 | 对象的存储开销 |
Proxy | 为其它对象提供一个代理以控制对这个对象的訪问。 | 怎样訪问一个对象;该对象的位置 |
Chain of Responsibility | 为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。
将这些对象连成一条链。并沿着这条链传递该请求。直到有一个对象处理它。 |
满足一个请求的对象 |
Command | 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行參数化;对请求排队或记录请求日志,以及支持可取消的操作。 | 何时、如何满足一个请求 |
Interpreter | 给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。 | 一个语言的文法及解释 |
Iterator | 提供一种方法顺序訪问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 | 对怎样遍历、訪问一个聚合的各元素 |
Mediator | 用一个中介对象来封装一系列的对象交互。中介者使各对象不须要显式地相互引用,从而使其耦合松散,并且能够独立地改变它们之间的交互。 | 对象间如何交互、和谁交互 |
Mementor | 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。 | 对一个对象中哪些私有信息存放在该对象之外。以及在对什么时候进行存储 |
Observer | 定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,全部依赖于它的对象都得到通知并自己主动刷新。 | 对多个对象依赖于另外一个对象。而这些对象又怎样保持一致 |
State | 同意一个对象在其内部状态改变时改变它的行为。
对象看起来似乎改动了它所属的类。 |
对象的状态 |
Strategy | 定义一系列的算法,把它们一个个封装起来, 而且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。 | 算法 |
Template Method | 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
Template Method使得子类能够不改变一个算法的结构就可以重定义该算法的某些特定步骤。 |
算法中的某些步骤 |
Visitor | 表示一个作用于某对象结构中的各元素的操作。它使你能够在不改变各元素的类的前提下定义作用于这些元素的新操作。 | 某些可作用于一个(组)对象上的操作,但不改动这些对象的类 |
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116389.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...