10分钟看懂常用设计模式

    前面的文章中,对常用的设计模式做了通俗的介绍,每篇中从问题的引入,到一般实现办法,到模式解决办法,最后分析模式的优缺点和适用场景。本片文章将对这些设计模式分类、对比,并将相似模式放在一起做适用分析。
    首先,设计模式是什么?它并不是由谁发明出来的一种技术,而是编程发展以来,人们在实际的开发中总是能遇到局部相似的一些问题,针对这些问题的相对好的解决经验进行提炼,提出了一套模式。类似于初等数学中,某一类的问题当你做的多了,自然就有了一套相对通用的解决方法,这个设计模式的道理是一样的。通过前面的介绍,可以看出大多数的模式都是基于面向对象的思想,也可以说设计模式的面向对象发展过程中,前人提炼出来的宝贵经验。模式不是固定不变的,因为问题复杂多变,没有绝对通用的办法。我们在解决问题的时候也会根据实际的情况做一些变通,但是设计模式为我们提供了宝贵的思路:怎样让你的程序更加的优雅、健壮。当养成了这种思维,脱离模式的设计反而是更上一个境界,这就是武学中的无招胜有招。但是在基本功不是很强的时候,老老实实的扎马步、练拳,永远是一个好的途径。
    设计模式可分为创建型 (Creational) ,结构型 (Structural) 和行为型 (Behavioral) 三种,其中 创建型模式主要用于描述如何创建对象结构型模式主要用于描述如何实现类或对象的组合行为型模式主要用于描述类或对象怎样交互以及怎样分配职责。

    创建型

    很明显,工厂模式、原型模式、建造者模式、单例模式这几个是创建型模式。这里的工厂模式又包括了:简单工厂、工厂方法、抽象工厂这三种。

    工厂三兄弟:简单工厂提供了最简单工厂模型,将所有类对象的创建逻辑封装在一个工厂类中。避免了在使用的地方到处的new和初始化,但是弊端是职责过重,不符合开闭。工厂方法为了解决上面的问题,为工厂也进行了分级,每个产品对应了一个工厂。但是弊端是工厂过多,编码的负担增重。抽象工厂是针对存在产品系列(产品簇)的情况,即当产品中,可以按照一定维度将同等级的不同产品组合在一起形成一个系列时,我们只为整个系列创建一个工厂。这样既解决简单工厂的职责过重,又减少了工厂方法方法的类数量。

    原型模式:当一类对象有一个或者少数几个固定的初始状态,或某类对象的初始状态可能运行时改变时,可以使用原型模式。通过保存包含这些初始状态的原型对象,然后clone得到一模一样的新对象。

    建造者模式:当一个复杂的对象是由多个具有不同具体类别的组件组成时,建造者模式可以使客户端指定一个总类别,然后透明的建造出最终对象提供给客户端。而且扩展新的组合时,负责开闭原则。如果组件间有一定的顺序依赖逻辑,该模式可以在抽象建造者中定义这种先后规则。

    单例模式:保持只有一个实例存在于系统中。

    

    结构型

   适配器:当已有的或外部提供的某个接口、功能模块,和现有的设计、系统不匹配,而无法直接对接使用时,可以提供一个抽象的适配器。然后具体的适配器实现它,在具体的适配器中再对需要被适配的接口进行包装调用,从而达到间接使用的目的。

    代理模式:代理模式是在被访问类前加上一个代理,对该类的实例的访问,都要经过代理的控制和限制。单客户端要可以透明的访问被代理的对象。可以通过代理类和被代理类实现相同接口/继承相同的抽象实现。

    装饰模式:装饰模式是在原油类的基础上,额外的增加一些新的职责和功能。也要客户端透明的使用,所以同样实现相同的抽象。

    门面模式:如果一个系统内部的逻辑都对外暴露使用,将会使之与外部的耦合度增加,扩展/修改困难。可以通过一个门面对外提供统一的服务,实质就是将内部逻辑封装在自己的范围内,做到解耦/隔离。同时,门面也要做到针对抽象,才能更好的应对变化。

    以上四个模式在几个方面具有有很大的相似性,但是仔细分析没一个模式的用途,就很好辨别。他们乍看上去,都是为已有的东西提供了一个新的访问途径,但是目的却都是不同的。适配器是为了将不兼容的东西连接到一起,改变了访问方式。门面模式也改变了访问方式,缺是为了将复杂的逻辑封装解耦。代理和装饰都是不改变访问方式,透明的使用,但是代理是为了对原有的功能进行控制/限制,而装饰模式是为了增加新的功能和职责,可以嵌套装饰。

    桥接模式: 适用于系统中的某类实体,存在多个维度的变化因素。将各个维度的抽象类组合成产品,动态的组合不同的实现类,来达到灵活的产生不同的结果。例如有两个维度,可以将一个维度用继承实现,另一个维度用”被继承的抽象父类“持有抽象接口类别的成员实现。多维度变化可以用同样的思想,变通实现。

    组合模式:当一个系统内的一个元素集合的逻辑结构是一个树形结构,既叶子结点都是不可分元素,而非叶子结点是若干节点的集合。例如集团下有CEO/董事/子公司。子公司就是集合,下面继续包含元素。通过各种元素都集成一个抽象父类,可以实现统一管理,灵活的配置。

    享元模式:当系统中有一些经常重复用到的小粒度元素存在时,可以将这些元素的不可变部分分离出来成为享元,在系统中缓存起来。这样每次用到的地方只需给予一个享元的引用,大大减少了内存占用。但是将类别抽象出可变与不可变(内部状态与外部状态)是不太容易的。

     

    行为型

    责任链模式:如果一个事件或消息,不只有一个处理者,而是一系列有先后甚至分支关系的处理者链,可以用责任链模式。抽象的处理者维护一个或多个下一级的处理者。客户端将事件交给一个入口后,就可以按照规则传递下去处理。可以灵活的组织成各种复杂的树形/网形的处理模型。

    命令模式:将请求或事件实例化成对象,将调用替换成对象的传递,这个做法可以做到很多事情。例如,请求的排队/持久化/异步化/log/操作备份/数据恢复/操作撤销等等。结合组合模式,可以实现宏命令,组合成许多复杂的功能。

    迭代器模式:对象内包含若干元素的集合,需要对外部提供遍历的服务。迭代器模式将遍历的逻辑与原逻辑隔离开,保持简单。同时两者都互相持有对方抽象类,可以做到自由的组合切换,增加灵活性和复用性。

    中介者模式:在曾经的游戏前端开发过程中,一件事很困扰我:多数用户行为影响的不止是一个实体,而是多个有关联的组件。他们之间牵一发动全身,可以使用中介中模式作为这些关系的统一管理者,针对每个行为对相关联的组件做出通知和调节,而不是每个组件的每个行为都去挨个通知关联的组件的相关处理方法,这样将网状结构iy变成了星状结构,更便于管理维护。更适用于复杂纠结的依赖关系。通过将组件统一抽象,将使中介者逻辑更加灵活,方便扩展。

    备忘录模式:某些特殊类的实例需要保存它们的历史状态,以便恢复/拷贝/持久化等等。备忘录模式通过提供备忘录类记录对象需要被记录的元素,保存状态。再通过备忘录管理类管理这些状态,提供访问途径。

    观察者模式:当一类对象的改变被多个其他的实例依赖时,将这些依赖对象称为观察者,被观察的对象维护观察者的一个集合,当放生事件时,主动的去通知观察者。

    模板方法模式:系统中总会有一些东西被无奈的按照一定的套路重复,实际可能每次不同的仅仅是其中一小部分。脑海里瞬间浮现JDBC。模板方法模式在抽象父类中规定了这些繁琐的规则,只将需要定制的部分留给实现类。极大的方便了客户端简洁的使用。利用钩子方法,又可以给予客户端一定的自由去控制这个规则,但是一切都是可控的。Spring在许多方面都利用了这个模式。脑海中瞬间又是JDBC。

    状态模式:某类实体可能根据属性具有多种不同的内部状态,并需要即时的动态切换。状态模式通过创建抽象状态类将状态与实体隔离,并可以灵活的切换和复用。

    策略模式:与状态模式类似,只不过状态模式是抽象出状态,而策略模式是抽象出行为。将某个具有多种选择的行为进行抽象隔离,实现动态切换和复用。

    访问者模式:系统产生一系列的信息,信息可能有多种细分类型,这些信息从不同层面分析具有多种价值,需要被多个不同目的逻辑处理。访问者模式将信息和访问逻辑分别抽象,可以将信息的出生与处理隔离,同时灵活的配置和切换处理的方案。又防止了多种逻辑混在一起的混乱。

    

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值