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方法被重载

  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/zhouxihi/p/6035113.html
Copyright © 2011-2022 走看看