设计模式与原则

七大设计原则

  • 单一职责原则:一个类负责一项职责。
  • 里式替换原则:继承与派生的规则。
  • 依赖倒置原则:高层次模块不应该依赖低层次模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。
  • 接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
  • 迪米特法则:低耦合、高内聚
  • 开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 组合、聚合复用原则:尽量使用组合和聚合少使用继承的关系来达到复用的原则。

二十四大设计模式

设计模式:为特定场景下的问题为指定的解决方案。

对象创建

  • 原形

使用原型实例制定创建对象的种类,并通过复制这个原型创建新的对象。

可以理解为模板,在创建新对象的时候,按照模板的方法来复制,避免重复造轮子。
优点
(1)可以避免内存较大开销的初始化创建动作。
(2)不用重新初始化对象,而是动态的获取对象运行时的状态。

  • 工厂方法(Factory Method

定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到其子类。也称为虚构造器。

优点:
从代码中消除了对应用程序特有类的耦合。
何时使用工厂方法:
(1)编译时无法准备预期要创建的对象的类
(2)类想让其子类决定在运行时创建什么
(3)若有若干辅助类为其子类,而你想将返回哪个子类型这一信息局部化

  • 抽象工厂(Abstract Factory

提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。抽象工厂提供了一个固定的接口,用于创建一系列有关联或相互依存的对象,而不必制定其具体类或其创建的细节。从工厂得到的具体对象之间没有耦合。

软件设计的黄金法则:变动需要抽象

抽象工厂工厂方法
通过对象组合创建抽象产品通过类继承创建抽象产品
创建多系列产品创建一种产品
必须修改父类接口才能支持新的产品子类化创建者并重载工厂方法以创建新产品
  • 简单工厂(Simple Factory

专门定义一个类来负责创建其他类的实例,被创建的实例常常具有共同的父类。
实际就是由一个工厂类,根据传入的参数,动态的决定创建出哪一个产品类的实例。

优点:
(1)客户端可以直接消费产品,而不必关心具体产品的实现。
(2)消除了客户端直接创建产品对象的责任,实现了对责任的分割。
缺点:
(1)工厂类集中了所有产品的设计逻辑,一旦不能正常工作,整个系统都会收到影响。
(2)当产品类别多结构复杂的时候,把所有创建工作放进一个工厂来,会使后期程序的扩展较为困难。
使用场景:
(1)工厂类负责创建的对象比较少时
(2)客户端只知道传入工厂类参数,对于如何创建对象的逻辑不必关心时。

  • 生成器(Builder

将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。

  • 单例(Singleton

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

优点:
(1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
(2)避免对资源的多重占用
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

接口适配

  • 适配器

将一个类的接口转化为客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

使用场景:
(1)已有类的接口和需求不匹配
(2)想要拥有一个可复用类,该类能够同可能带有不兼容接口的其他类协作
(3)想要适配一个类的不同子类,可是让一个子类去子类化一个类适配器又不现实,可以使用对象适配器来适配其父类的接口。
在这里插入图片描述

  • 桥接

将抽象部分与他的实现部分分离,使得他们都可以独立的变化。

何时使用桥接模式:
(1)不想在抽象与其实现之间形成固定的绑定关系。
(2)抽象及其实现都可以通过子类化独立进行扩展
(3)对抽象的实现进行修改不影响客户端代码
(4)如果每个实现需要额外的子类以细化抽象,则说明有必要把他们分成两个部分
(5)想在带有不同抽象接口的多个对象之间共享一个实现

  • 外观

为系统中的一组接口提供一个统一的接口。外观定义了一个高层接口,让子系统更易于使用。

使用场景:
(1)子系统正逐渐变得复杂。应用模式的过程中演化出很多类,可以使用外观为这些子系统提供一个较简单的接口。
(2)可以使用外观对子系统进行分层。每个子系统级别有一个外观座位入口点。

对象去耦

  • 中介者

用一个对象来封装一系列对象的交互方式。中介者使各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。

使用场景:

(1)对象间的交互虽然定义明确,然而非常复杂,导致一组对象比例相互依赖而且难以理解。
(2)因为对象引用了许多其他对象并与其通讯,导致对象难以复用。
(3)想要定制一个分布在多个类中的逻辑或行为,又不想生成太多子类。

  • 观察者

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

使用场景:
(1)有两种抽象类型相互依赖,将他们封装在各自的对象中,就可以对他们单独进行改变和复用。
(2)对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
(3)一个对象必须通知其他对象,而他又不需知道其他对象是什么

抽象集合

  • 组合

将对象组合成树形结构以表示“部分-整体”的结构层次。组合使用户对单个对象和组合对象的使用具有一致性。

  • 迭代器

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

外部迭代器:
(1)客户端需要知道外部迭代器才能使用,但是它为客户端提供了更多的控制。 (2)客户端创建并维护外部迭代器
(3)客户端可以使用不同外部迭代器实现多种类型的遍历
内部迭代器:
(1)客户不需要知道任何外部迭代器,而是可以通过集合对象的特殊接口,或者一次访问一个元素,或者向集合中的每个元素发送消息
(2)集合对象本身创建并维护他的外部迭代器
(3)集合对象可以在不修改客户端代码的情况下,选择不同的外部迭代器
使用场景:
(1)需要访问组合对象的内容,而又不暴露其内部表示
(2)需要通过多种方式遍历组合对象
(3)需要提供一个统一的接口,用来遍历各种类的组合对象

行为扩展

  • 访问者

表示一个作用于某对象结构中的各元素的操作。他让我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

使用场景:
(1)一个复杂的对象结构包含很多其他对象,他们有不同的接口,但是想对这些对象实施一些依赖于其具体类型的操作
(2)需要对一个组合结构中的对象进行很多不相关的操作,但是不想让这些操作“污染”这些类的对象
(3)可以将相关的操作集中起来,定义在一个访问者类中,并在需要在访问者中定义的操作时使用它
(4)定义复杂结构的类很少做修改,但经常需要向其添加新的操作。
优点:
添加操作,只需实现具体的访问者,不会对类的结构造成破坏。
缺点:
访问者与目标类耦合在一起,因此,如果访问者需要支持新类,访问者的父类和子类都需要修改,才能反应新的功能。

  • 装饰

动态的给一个对象添加一些额外的职责,就是扩展功能,装饰模式相比生成子类更为灵活。

总结:
(1)装饰者包含被装饰者的所有接口和引用,方法实现完全是引用调用自己的方法,在装饰者子类添加新功能。
(2)分类主要用于对被装饰者类的方法拓展,与本设计模式稍有区别。

  • 责任链

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间发生耦合。此模式将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

优点:
任何攻击处理程序都能在任何时间被添加/删除,而不会影响人物的其他行为。在开发中的应用:用户的信息录入校验(层层校验)。

算法封装

  • 模板方法

定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使子类可以重定义算法的某些特定步骤而不改变算法的结构。将共有实现抽到父类方法,重写父类方法,实现自己特有

使用场景:
(1)需要一次性实现算法的不变部分,并将可变的行为留给子类来实现
(2)子类的共同行为应该被提取出来放到公共类中,以避免代码重复
(3)需要控制子类的扩展

  • 策略

定义一系列算法,把他们一个个封装起来,并且使他们可以相互替换。本模式使得算法可独立于使用它的客户而变化。
把每个算法封装成一个对象,消除根据数据类型决定使用什么算法的一堆if-else或switch-case
如果代码中有很多条件语句,就可能意味着需要把他们重构成各种策略对象

优点:
解决代码的耦合度。
缺点:
为了解决代码的耦合度,需要创建更多的类。

  • 命令

将请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。命令模式还可以推迟调用器的执行

使用场景:
(1)想让应用程序支持撤销和删除
(2)想让对象参数化一个动作以执行操作,并用不同命令对象来代替回调函数
(3)想要在不同时刻对请求进行指定、排列和执行
(4)想记录日志,这样在系统故障时,这些修改可在后来重做一遍。
(5)想让系统支持事务,事务封装了对数据的一系列修改,事务可以建模为命令对象。

性能与对象访问

  • 享元

运用共享技术有效的支持大量细粒度的对象。

使用场景:
(1)应用程序使用很多对象
(2)在内存中保存对象会影响内存性能
(3)对象的多数也有状态可以放到外部而轻量化
(4)移除了外在对象之后,可以用较少的共享对象代替原来的那组对象
(5)应用程序不依赖于对象标识,因为共享对象不能提供唯一的标识

  • 代理

为其他对象提供一种代理以控制对这个对象的访问

对象状态

  • 备忘录

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。

使用场景:

  • 需要保存一个对象在某个时刻的状态,这样以后就可以恢复到先前的状态
  • 用于获取状态的接口会暴露实现的细节,需要将其隐藏起来
    感谢并参考:
    https://www.jianshu.com/p/d3296debe236
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值