新设计模式

迭代器模式

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
其实也就是不使用对象原有迭代的方式,自己封装的迭代方式。封装后可以根据自己的需求添加,修改,删除,过滤等操作。

迭代器有以下角色:

迭代器模式主要包含以下角色:

抽象聚合(Aggregate)角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。

具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。

抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。

具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

代码实现:

// 迭代器模式,不暴漏原始迭代方法,使用封装的方法来代理迭代对象
    class Iteration {
      constructor (object) {
        this.object = object
        this.current = 0
        this.all = object.length || Object.keys(object).length
        this.keys = Object.keys(object)
      }
      next () {
        if (this.current === this.all) { return null }
        else {
          let value = this.object[this.keys[this.current]]
          this.current++
          return value
        }
      }
    }
    let tobj = {a:5,b:6,c:7}
    let tobjIter = new Iteration(tobj)
    let value = tobjIter.next()
    while(value) {
      console.log(value)
      value = tobjIter.next()
    }

中介者模式

如果在一个系统中对象之间的联系呈现为网状结构。对象之间存在大量的多对多联系,将导致系统非常复杂,这些对象既会影响别的对象,也会被别的对象所影响,这些对象称为同事对象,它们之间通过彼此的相互作用实现系统的行为。在网状结构中,几乎每个对象都需要与其他对象发生相互作用,而这种相互作用表现为一个对象与另外一个对象的直接耦合,这将导致一个过度耦合的系统。

而 “迪米特法则”告诉我们,可以引入一个“第三者”来降低现有系统中类之间的耦合度。

中介者模式可以使对象之间的关系数量急剧减少,通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构 ,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。

【迪米特法则:(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。】

定义

如果在一个系统中对象之间存在多对多的相互关系,我们可以将对象之间的一些交互行为的细节从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行统一协调,这样对象之间多对多的复杂关系就转化为相对简单的一对多关系。通过引入中介者来简化对象之间的复杂交互,中介者模式是“迪米特法则”的一个典型应用。
又叫调停模式,定义一个中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

中介者模式包含以下主要角色:

抽象中介者接口(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法(通信)。
具体中介者(ConcreteMediator)角色:实现中介者接口, 是抽象中介者的子类 ,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系, 维持了对各个同事对象的引用 ,因此它依赖于同事角色。
抽象同事类(Colleague)角色: 它定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
具体同事类(Concrete Colleague)角色: 它是抽象同事类的子类;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中声明的抽象方法。

代码实现:

// 中介者模式,对象比较多的时候,想要访问其他对象会非常麻烦,这时候可以使用中介者来访问对象

    class Middle{
      constructor() {}
      addObject (object, name) {
        this[name] = object
      }
    }
    let mid = new Middle()
    let ta = {
      a: 10,
      b: 5,
      del () {
        delete this.a
      },
      add (value) {
        this.b += value
      }
    }

    let tb = {
      a: 20,
      b:15,
      read() {
        return this.a + this.b
      }
    }
    mid.addObject(ta, 'ta')
    mid.addObject(tb, 'tb')

    mid.ta.add.call(tb, 15)
    console.log(tb.b)

享元模式

面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。享元模式正式为解决这一类问题而诞生的。
享元模式(Flyweight Pattern)又称轻量级模式,是对象池的一种实现。类似于线程池,线程池可以不停的创建和销毁多个对象,消耗性能。提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细颗粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,从此来降低内存的消耗,属于结构性模式。
享元模式把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
享元模式的本质是缓存共享对象,降低内存消耗。
享元模式有三个参与角色:
抽象享元角色(IFlyweight):享元对象抽象基类或者接口,同时定义出对象的外部状态和内部状态的接口或者实现;

具体享元角色(ConcreteFlyweight):实现抽象角色定义的业务。该角色的内部状态处理应该与环境无关,不能出现会有一个操作改变内部状态 ,同时修改了外部状态

享元模式的应用场景

当系统中多处需要同一组信息时,可以吧这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象多次创建,消耗大量内存空间。
享元模式其实就是工厂模式的一个改进机制,��元模式同样要求创建一个或一组对象,并且就是通过工厂方法生成对象的,只不过享元模式中为工厂方法增加了缓存这一功能。主要总结为以下应用场景:

1、常常应用于系统底层的开发,以便解决系统的性能问题。
2、系统有大量相似的对象、需要缓存池的场景。

在生活中的享元模式也很常见,比如中介机构的房源共享,再比如全国社保联网。

代码实现:

// 享元模式, 如果一些信息在多处都需要调用,可以把它封装成一个对象,在使用的地方引用,避免多次创建重复信息的对象
    // 这里假设是个餐厅,食材信息是固定的,每道菜的分量成本就可以通过使用了多少mer1,和多少mer2,来计算
    let mer1 = {
      weight: 5,
      money: 10
    }
    let mer2 = {
      weight: 8,
      money:7
    }

    class Food1  {
      constructor(mer1, mer2) {
        this.mer1 = mer1
        this.mer2 = mer2
      }
      makeFood () {
         
      }
      get price () {
        return this.mer1.money * 2 + this.mer2.money
      }
    }

    class Food2  {
      constructor(mer1, mer2) {
        this.mer1 = mer1
        this.mer2 = mer2
      }
      makeFood () {
         
      }
      get price () {
        return this.mer1.money + this.mer2.money * 3
      }
    }

    let food1 = new Food1(mer1, mer2)
    let food2 = new Food2(mer1, mer2)
    console.log(food1.price, food2.price)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 关于这篇文章本人的体悟,要彻底理解面向对象思想,一切从面向对象的思想触发去理解学习。摒弃面向过程的业务思维将实际工...
    牧童US阅读 1,003评论 0 4
  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,772评论 0 14
  • 学习并理解 23 种设计模式 设计模式 Design Pattern 是一套被反复使用、多数人知晓的、经过分类编目...
    Code_Narrator阅读 1,047评论 0 1
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,961评论 1 15
  • 常用十大设计模式 一、设计模式概述 1.1软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用...
    Zerek_W阅读 493评论 0 0