迭代器模式
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
其实也就是不使用对象原有迭代的方式,自己封装的迭代方式。封装后可以根据自己的需求添加,修改,删除,过滤等操作。
迭代器有以下角色:
迭代器模式主要包含以下角色:
抽象聚合(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)