zoukankan      html  css  js  c++  java
  • Objective-C 装饰模式--简单介绍和使用

    装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

    比如游戏机有一个GamePad类, 现在要增加一个作弊功能(例如100条命), 如果直接在GamePad类中去添加可能会影响其他子类的使用

    我们考虑装饰模式思维, 先建立一个装饰器实现GamePad的所有功能, 然后在装饰器类的子类中去添加作弊放方法

    上代码

    比如GamePad类是这样

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface GamePad : NSObject
     4 
     5 - (void)up;
     6 - (void)down;
     7 - (void)left;
     8 - (void)right;
     9 - (void)buttonA;
    10 - (void)buttonB;
    11 
    12 @end

    我们创建一个装饰器类, 让它持有一个GamePad实例并实现相同的方法接口

    GamePadDecorator.h

     1 #import <Foundation/Foundation.h>
     2 #import "GamePad.h"
     3 
     4 @interface GamePadDecorator : NSObject
     5 
     6 - (void)up;
     7 - (void)down;
     8 - (void)left;
     9 - (void)right;
    10 - (void)buttonA;
    11 - (void)buttonB;
    12 
    13 @end

    GamePadDecorator.m

     1 #import "GamePadDecorator.h"
     2 
     3 @interface GamePadDecorator ()
     4 
     5 @property (nonatomic, strong) GamePad *gamePad;
     6 
     7 @end
     8 
     9 @implementation GamePadDecorator
    10 
    11 - (instancetype)init {
    12     self = [super init];
    13     if (self) {
    14         self.gamePad = [[GamePad alloc] init];
    15     }
    16     return self;
    17 }
    18 
    19 - (void)up {
    20     [self.gamePad up];
    21 }
    22 
    23 - (void)down {
    24     [self.gamePad down];
    25 }
    26 
    27 - (void)left {
    28     [self.gamePad left];
    29 }
    30 
    31 - (void)right {
    32     [self.gamePad right];
    33 }
    34 
    35 - (void)buttonA {
    36     [self.gamePad buttonA];
    37 }
    38 
    39 - (void)buttonB {
    40     [self.gamePad buttonB];
    41 }
    42 
    43 @end

    现在我们新增一个子类来实现作弊方法

    CheatGamePadDecorator.h

    1 #import "GamePadDecorator.h"
    2 
    3 @interface CheatGamePadDecorator : GamePadDecorator
    4 
    5 - (void)cheat;
    6 
    7 @end

    CheatGamePadDecorator.m

    1 #import "CheatGamePadDecorator.h"
    2 
    3 @implementation CheatGamePadDecorator
    4 
    5 - (void)cheat {
    6     NSLog(@"cheat");
    7 }
    8 
    9 @end

    这样我们就可以直接在Controller中直接用CheatGamePadDecorator类去实现GamePad的所有功能还能额外实现作弊方法

     1 #import "ViewController.h"
     2 #import "CheatGamePadDecorator.h"
     3 
     4 @interface ViewController ()
     5 
     6 @end
     7 
     8 @implementation ViewController
     9 
    10 - (void)viewDidLoad {
    11     [super viewDidLoad];
    12     
    13     //创建CheatGamePadDecorator实例
    14     CheatGamePadDecorator *cheaterGamePad = [[CheatGamePadDecorator alloc] init];
    15     
    16     //实现GamePad的功能
    17     [cheaterGamePad up];
    18     [cheaterGamePad down];
    19     
    20     //实现作弊方法
    21     [cheaterGamePad cheat];
    22 }
    23 
    24 
    25 
    26 @end

    这样就完成了一个装饰模式思路的代码构建

    下面说说cocoa touch中自带的Category, 它也是对装饰模式的一个实现

    我们用Category来实现上面GamePad添加作弊功能

    我们创建一个Cheat Category

    GamePad+Cheat.h

    1 #import "GamePad.h"
    2 
    3 @interface GamePad (Cheat)
    4 
    5 - (void)cheat;
    6 
    7 @end

    GamePad+Cheat.m

    1 #import "GamePad+Cheat.h"
    2 
    3 @implementation GamePad (Cheat)
    4 
    5 - (void)cheat {
    6     NSLog(@"cheat");
    7 }
    8 
    9 @end

    这样我们就可以直接在Controller中通过Category来实现上面功能

     1 #import "ViewController.h"
     2 #import "GamePad+Cheat.h"
     3 
     4 @interface ViewController ()
     5 
     6 @end
     7 
     8 @implementation ViewController
     9 
    10 - (void)viewDidLoad {
    11     [super viewDidLoad];
    12     
    13     //创建GamePad实例
    14     GamePad *gamePad = [[GamePad alloc] init];
    15     
    16     //实现GamePad原有方法
    17     [gamePad up];
    18     [gamePad down];
    19     
    20     //实现作弊方法
    21     [gamePad cheat];
    22     
    23 }

    使用Category更为简单

    但是在使用Category时有个细节一定要注意, 尽量不要在Category类中去重写基类方法

    假如我们在GamePad+Cheat.h中重写了- (void)up方法, 则整个工程中的up方法都被重载了

    即使我们不在任何地方引用GamePad+Cheat.h, 只要这个文件在工程里面就会让GamePad方法被重载

  • 相关阅读:
    plsqldeveloper永久注册码
    git常用命令
    淘淘中的一些环境的处理
    Hibernate查询
    markdown的学习
    npm如何发布一个自己的package
    聊聊font-family的那些事
    js 随机生成任意长度的字符串
    CSS世界(张鑫旭)系列学习总结 (四)盒尺寸四大家族
    CSS世界(张鑫旭)系列学习总结 (三)width和height作用的具体细节
  • 原文地址:https://www.cnblogs.com/zhouxihi/p/6035113.html
Copyright © 2011-2022 走看看