设计模式(二)----桥接模式、适配器模式、外观模式、组合模式、装饰模式、享元模式、代理模式

桥接模式

要实现多个有相同的类的操作,他们又有各自的控制单元,如车控钥匙控制车辆的上锁、解锁。如果每种钥匙都对应每种车辆的话,具体代码会剧增。我们可以将车辆型号和钥匙隔控制逻辑离开来。钥匙的同一操控可以复用和扩展,而不会影响其他电视剧型号。桥接的目标是把抽象层次结构从实现中分离出来,让它能够独立变更。

桥接模式类图:


桥接模式类图.png

图中我们可以通过UniversalApp来实现对MoBike和OFOBike的控制操作,他们通过各自的抽象类进行桥接在一起,实现控制与实现的分离。

UniversalApp模型的实现

- (void)lock
{
    [self sendCommand:Command_lock];
}
- (void)open
{
    [self sendCommand:Command_open];
}
- (void)broken
{
    [self sendCommand:Command_broken];
}
- (void)reserve
{
    [self sendCommand:Command_reserve];
}

App模型的实现

- (void)sendCommand:(Command)command
{
    [self.bike receiveCommand:command];
}

本节工程示例

适配器模式

在一些应用中,我们创建的类已经拥有的一定的行为,而我们客户端需要拥有自己定义的行为,我们就可以使用适配器模式,将原有的行为传递给使用者。例如像我们大陆去香港购物,香港当地是用港币结算,但在大陆习惯用人民币来衡量物品的价值,这时候的思维往往会用港币转换成人民币来计算,这时我们就可以用适配器模式来适配港币的结算来获得人民币的价值。实现适配器模式有两种方式,已是通过继承适配者,调用父类方法来适配,也称为类适配。另一种是通过组合方式,持有适配对象,来实现适配功能。

类适配器模式类图


类适配器模式类图.png

适配功能在Adapter_Class的实现中进行,调用父类的方法,进行操作。

Adapter_Class的实现

const float rate = 0.82;

@implementation Adapter_Class

- (float)getSellPriceUseCNY
{
    return [super getSellPriceUseHKD] * rate;
}

@end

对象适配器模式类图


对象适配器模式类图.png

Adapter_Object的实现

const float rate_o = 0.82;

@implementation Adapter_Object

- (instancetype)init
{
    if (self = [super init]) {
        _goods = [[HKGoods alloc] init];
    }
    return self;
}

- (float)getSellPriceUseCNY
{
    return [self.goods getSellPriceUseHKD] * rate_o;
}

@end

本节工程示例

外观模式

在一些子系统逐渐复杂的应用场景中,我们可以将一组不同的接口提供统一接口。定义上层接口,通过降低复杂度和隐藏子系统间的通信及依存关系,让子系统更易于使用。例如在使用XMPP协议的登录过程,我们在登录的时候分好几个步骤,同时UI也会跟随着登录状态进行相应的变化,我们可以统一成一个登录接口,供客户端调用。使用这种方式让子系统更容易使用的方式就是外观模式。

外观模式类图:


外观模式类图.png

客户端要实现登录功能,只需调用LoginManager的loginAction方法即可完成UI变化和XMPP登录的一整套流程,简化了登录的调用。
其中登录接口的实现

- (void)loginAction
{
    
    XMPPLogin *login = [[XMPPLogin alloc] init];
    UIStatue *ui = [[UIStatue alloc] init];
    
    [ui logining];
    [login connetXMMPServer];
    [login authenticationPassWord];
    [login xmppDidAuthenticate];
    [ui logined];
}

本节工程示例

组合模式

把一些相同基类型的对象组合到树状结构中,父节点包含同类型的子节点,像平时公司的组织架构、家族结构、公司同一系列产品都可以使用这种模式。拿公司组织架构来说,公司包含多个部门,部门又包含多个员工。我们可以通过统一的接口把这整个复杂结构作为一个整体来使用,如通知公司放假、公司传达到各个部门,各个部门再通知下面的员工。其实也就是将对象组合成“部分-整体”的关系,让其中的每个节点具有相同的抽象接口。

组合模式类图:


组合模式类图.png

MemberModel定义了统一的接口,它的操作可以通过递归传达到借点的每一处。

其中Company的实现

- (void)addMember:(id <MemberModel>)member
{
    [self.childMembers addObject:member];
}
- (void)removeMember:(id <MemberModel>)member
{
    [self.childMembers removeObject:member];
}

- (instancetype)init
{
    if (self = [super init]) {
        _childMembers = [NSMutableArray<MemberModel> array];
    }
    return self;
}

本节工程示例

装饰模式

有些时候我们需要对现有的行为进行一定的修饰,又希望不改变原有的功能,我们就可以使用装饰模式,也是动态的给一个对象添加一些扩展功能。例如就跑步来说,最开始只有跑步的功能,现在在不需要改变原有的功能上,给它加点快跑和慢跑的修饰。我们抽象一个父类,细化另一个抽象类,这个抽象类包含了父类中的一个引用,具体的修饰行为交给他的子类来表示。

装饰模式类图:


装饰模式类图.png

MemberModel定义了统一的接口,它的操作可以通过递归传达到借点的每一处。

其中RunDecorator的实现

- (instancetype)initWithRun:(id<RunProtocol>)runer
{
    self = [super init];
    if (self) {
        _runer = runer;
    }
    return self;
}

- (NSString *)run
{
    return nil;
}

除了以上的这种装饰方式外,在OC中还可以使用类别来进行装饰,它装饰饰的方式是编译时绑定的,而且它成为了类的一部分。但在一些简单装饰的话,可以用类别来实现,使用起来更为简洁方便。

本节工程示例

享元模式

在应用程序要使用很多对象,我们可以共享这些对象的一些共同点,以节省内存空间。就像奥运会一样,每一场比赛都需要比赛场地,我们不可能每场比赛都使用新的场馆,现实没那么多的场地资源支撑,同一类型的比赛使用同一场地,这样可以节省很多资源。就像我们需要某种资源了,看看是否已经拥有,有的话就直接使用,没有再创建,也就是共享可用对象。

享元模式类图:


享元模式类图.png

PlaygroudFactory定义工厂方法,它利用缓存池来保证对象的共享使用。

其中PlaygroudFactory的实现部分

- (id<Playground>)playgroudWithStation:(PlaygroudStation)station
{
    if (self.playgroudPools == nil) {
        self.playgroudPools = [[NSMutableDictionary alloc] initWithCapacity:kTotalNumberPlaygroud];
    }
    
    BJPlaygroud *playgroud = [self.playgroudPools objectForKey:[NSNumber numberWithInteger:station]];
    
    if (playgroud == nil) {
        
        playgroud = [[BJPlaygroud alloc] init];
        
        switch (station) {
            case kPlaygroud_NationalStadium:
                playgroud.name = @"国家体育场";
                playgroud.events = @"田径、足球";
                break;
                
            case kPlaygroud_NationalAquaticsCenter:
                playgroud.name = @"国家游泳中心";
                playgroud.events = @"游泳";
                break;
                
            case kPlaygroud_NationalIndoorStadium:
                playgroud.name = @"国家体育馆";
                playgroud.events = @"体操、蹦床、手球";
                break;
            case kPlaygroud_ShootingRangeHall:
                playgroud.name = @"北京射击馆";
                playgroud.events = @"射击";
                break;
                
            default:
                break;
        }
        [self.playgroudPools setObject:playgroud forKey:[NSNumber numberWithInt:station]];
    }
    
    return playgroud;
}

本节工程示例

代理模式

为其他对象提供一种代理以控制对这个对象的访问。例如我要购买火车票,如果需要跑到车站去买的话,会花很多时间,这个时候我就可以找个附近的代售点进行购买。除了像这种情况,还可以创建重型对象,来延迟加载和调用,根据不同的访问权限控制对原对象的访问也可以使用这种方式。

代理模式类图:


代理模式类图.png

客户端要进行买票操作的时候,通过代理对象调用上层抽象接口,来实现实际售票对象的卖票功能,其中CommissionMerchant的实现部分

- (instancetype)init
{
    self = [super init];
    if (self) {
        _station = [[Station alloc] init];
    }
    return self;
}

- (void)sellTicket
{
    [self.station sellTicket];
}

本节工程示例

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

推荐阅读更多精彩内容