设计模式之结构型模式(上)

GoF 归纳整理的23个设计模式依据其目的可以分为创建型(Creational)、结构型(Structural)和行为型(Behavioral)三种。关于创建型模式上次我已经写过一篇文章了,这次就说一说结构型模式。

顾名思义,结构型模式的目的主要就是组合类和对象以获得一个更大更合适的结构,具体包括适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式和代理模式。本文主要介绍前三种模式,剩余的留待下期再论。

适配器(Adapter)

适配器模式的目的是在不改变已有类(被适配者)的前提下,用一个新类(适配器)去继承或者组合它,然后对外提供符合需求的接口。

设计模式的分类遵从目的准则和范围准则,像创建型、结构型、行为型这样的分法是基于目的准则的,而像类模式、对象模式这样的分法则是基于范围准则。类模式是指那些主要针对类,使用继承来实现的模式;对象模式是指那些主要使用对象组合来实现的模式。对象模式可以在运行期改变对象组合,所以比类模式更灵活更动态。适配器模式可以通过多继承和对象组合实现,所以说适配器模式既可以是类模式,也可以是对象模式。

以 Swift 举个例子(Swift 不支持多继承,但支持实现多个协议):

protocol Animal {
    //...
    func move()
}

class Bird {
    //...
    func fly() {
        print("Bird is flying.")
    }
}

func playWithAnimal(animal: Animal) {
    print("----Play----")
    animal.move()
}

假设Bird是一个早已存在的类,我们现在想把让它用到playWithAnimal这个方法里去,但显然是不能直接用的,当然也不能轻易去修改它,因为它可能跟很多其他的类有关联,一旦轻易修改就可能造成连锁 Bug。这个时候就可以让适配器模式来一展拳脚了。

首先,我们使用类适配器,新建一个BirdAdapter继承Bird:

class BirdClassAdapter: Bird, Animal {
    func move() {
        fly()
    }
}

let bird = BirdClassAdapter()
playWithAnimal(bird)

这样就可以正常调用了,而且不会影响到原有的类。

接下来我们使用对象适配器,新建一个BirdAdapter来组合Bird对象:

class BirdObjectAdapter: Animal {
    var bird: Bird
    init(bird: Bird) {
        self.bird = bird
    }
    
    func move() {
        bird.fly()
    }
}

let bird = BirdObjectAdapter(bird: Bird())
playWithAnimal(bird)

类适配器可以在适配器中重写Bird类的方法,而且可以做到双重适配,也就是说在原先用到Bird类的地方也可以使用BirdClassAdapter,这点是对象适配器做不到的。但对象适配器可以适配Bird的所有子类,即在初始化BirdObjectAdapter时可以传入Bird及其子类。

桥接模式(Bridge)

桥接模式的目的是为了将抽象部分与实现部分分离,使它们可以独立变化,以适应系统的不断发展。所以与适配器模式不同,桥接模式一般是在系统设计之初就开始使用以应对未来的变化,而不是在一个已经存在很久的旧系统中做一些修修补补的适配工作。

桥接模式的形式其实也很简单,就是利用对象组合分离接口和实现,用继承来分别扩充接口和实现:

// 抽象(暴露给客户使用的接口)
class Abstraction {
    var imp: Implementor
    
    init(imp: Implementor) {
        self.imp = imp
    }
    
    func operation() {
        imp.operationImp()
    }
}

// 对接口的扩展
class RefinedAbstraction: Abstraction {
    func otherOperation() {}
}

// 实现
protocol Implementor {
    func operationImp()
}

// 对实现的扩展
class ConcreteImplementor: Implementor {
    func operationImp() {
        print("Do something.")
    }
}

AbstractionImplementor之间就是所谓的桥接关系,两者可以独立变化,并隐藏大量实现细节。

组合(Composite)

Composite 模式(翻译成组合模式总感觉怪怪的)将对象组合成树形结构以表示“部分-整体”的层次结构,使单个对象和组合对象对外表现出一致的接口。

Composite 对象结构.png

上图是 Composite 模式的典型结构图,Composite表示组合对象,Leaf表示单个对象,都继承自Component(图中未出现)。Component是对外提供的接口,它一般包含Add(Component)Remove(Component)GetChild(int)以及通用的Operation()等方法。看到这里是不是感觉有点眼熟?其实 iOS 开发者整天都在跟 Composite 模式打交道,因为 UIKit 就是基于 Composite 模式构建的。UIView 就是 Component,UIView 的所有子类,比如 UIImage、UILabel 等等,都既可以作为 Composite 又可以作为 Leaf。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容