iOS设计模式---访问者模式

一个简单的Car模型,含有1台Engine、4个Wheel,使用访问者模式添加对Car的升级与维修操作。

定义Engine类:

//
//  NimoEngine.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@interface NimoEngine : NSObject

@property (nonatomic, copy) NSString *modelName;
- (id)initWithModelName:(NSString *)modelName;

@end
//
//  NimoEngine.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoEngine.h"

@implementation NimoEngine

- (id)initWithModelName:(NSString *)modelName
{
    self = [super init];
    if (self) {
        _modelName = [modelName copy];
    }
    return self;
}

- (id) init
{
    return [self initWithModelName:@"Slant 6"];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"Engine: %@", _modelName];
}

@end

定义Wheel类:

//
//  NimoWheel.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NimoWheel : NSObject

@property (nonatomic, assign) float diameter; //车轮直径

@end
//
//  NimoWheel.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoWheel.h"

@implementation NimoWheel

- (id)init
{
    self = [super init];
    if (self) {
        _diameter = 400.0f;
    }
    return self;
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"Wheel: %f mm", _diameter];
}

@end

定义Car类:

//
//  NimoCar.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>

@class NimoEngine, NimoWheel;

@interface NimoCar : NSObject

@property (nonatomic) NimoEngine *engine;
@property (nonatomic, readonly) NSArray *arrayOfWheels;

- (void)addWheel:(NimoWheel *)wheel atIndex:(NSUInteger) index;

@end
//
//  NimoCar.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

@interface NimoCar()

@property (nonatomic, readwrite) NSMutableArray *mutableArrayOfWheels;

@end

@implementation NimoCar

- (id)init
{
    if (self = [super init]) {
        _mutableArrayOfWheels = [[NSMutableArray alloc] initWithCapacity:4];
    }
    
    return self;
}

- (void)addWheel:(NimoWheel *)wheel atIndex:(NSUInteger) index
{
    [_mutableArrayOfWheels insertObject:wheel atIndex:index];
}

- (NSArray *)arrayOfWheels
{
    return [_mutableArrayOfWheels copy];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"My car: %@", [NSDictionary dictionaryWithObjects:@[_engine, self.arrayOfWheels] forKeys:@[@"Engine", @"Wheels"]]];
}

@end

我们的汽车结构很简单,只包含1个引擎,4个车轮,并且各个类也没有复杂的实现,仅仅覆写了description,让其输出简要的信息。

好,实例化一辆Car, 看看效果:

//
//  main.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoCar.h"
#import "NimoEngine.h"
#import "NimoWheel.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NimoCar *car = [[NimoCar alloc] init];
        NimoEngine *engine = [[NimoEngine alloc] initWithBrandName:@"V8"];
        NimoWheel *wheelA = [[NimoWheel alloc] init];
        NimoWheel *wheelB = [[NimoWheel alloc] init];
        NimoWheel *wheelC = [[NimoWheel alloc] init];
        NimoWheel *wheelD = [[NimoWheel alloc] init];
        
        car.engine = engine;
        [car addWheel:wheelA atIndex:0];
        [car addWheel:wheelB atIndex:1];
        [car addWheel:wheelC atIndex:2];
        [car addWheel:wheelD atIndex:3];
        
        NSLog(@"%@", car);
        
    }
    return 0;
}

控制台跟意料中一样输出了Car的信息。至此,准备工作做好了。

      访问者模式:表示一个作用于某对象结构中的各元素的操作。它让我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。---《设计模式》(Addison-Wesley, 1994)

这段话比较拗口,不太好理解。拿刚刚完成的Car类来举例,NimoCar类就是对象结构,其中包含的元素为:NimoEngine类和NimoWheel类。如果现在需要对Car进行全面升级(新操作),通常的做法是NimoEngine与NimoWheel都向外提供“升级”的接口。如果还需要对Car进行维修呢?那又得向外提供“维修”的接口。随着类似的需求越多,NimoEngine与NimoWheel向外提供的接口就越多,类也变得越复杂。有没有简单的方法呢?有!把这些琐事都交给访问者来做吧,NimoEngine与NimoWheel只要同意被访问就成。

定义访问者协议:

//
//  ComponentVisitor.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

@class NimoEngine, NimoWheel;

@protocol NimoComponentVisitor <NSObject>

- (void) visitEngine:(NimoEngine *) engine;
- (void) visitWheel:(NimoWheel *) wheel;

@end

修改我们的类,使其能够接受访问

添加访问支持的Engine类:

//
//  NimoEngine.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@interface NimoEngine : NSObject

@property (nonatomic, copy) NSString *modelName;

- (id)initWithModelName:(NSString *)modelName;

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor;

@end
//
//  NimoEngine.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoEngine.h"

@implementation NimoEngine

- (id)initWithModelName:(NSString *)modelName
{
    self = [super init];
    if (self) {
        _modelName = [modelName copy];
    }
    return self;
}

- (id) init
{
    return [self initWithModelName:@"Slant 6"];
}

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor
{
    [visitor visitEngine:self];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"Engine: %@", _modelName];
}

@end

添加访问支持的Wheel类:

//
//  NimoWheel.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@interface NimoWheel : NSObject

@property (nonatomic, assign) float diameter; //直径

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor;

@end
//
//  NimoWheel.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoWheel.h"

@implementation NimoWheel

- (id)init
{
    self = [super init];
    if (self) {
        _diameter = 400.0f;
    }
    return self;
}

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor
{
    [visitor visitWheel:self];
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"Wheel: %f mm", _diameter];
}

@end

添加访问支持的Car类

//
//  NimoCar.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@class NimoEngine, NimoWheel;

@interface NimoCar : NSObject

@property (nonatomic) NimoEngine *engine;
@property (nonatomic, readonly) NSArray *arrayOfWheels;

- (void)addWheel:(NimoWheel *)wheel atIndex:(NSUInteger) index;

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor;
@end
//
//  NimoCar.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoCar.h"
#import "NimoEngine.h"
#import "NimoWheel.h"

@interface NimoCar()

@property (nonatomic, readwrite) NSMutableArray *mutableArrayOfWheels;

@end

@implementation NimoCar

- (id)init
{
    if (self = [super init]) {
        _mutableArrayOfWheels = [[NSMutableArray alloc] initWithCapacity:4];
    }
    
    return self;
}

- (void)addWheel:(NimoWheel *)wheel atIndex:(NSUInteger) index
{
    [_mutableArrayOfWheels insertObject:wheel atIndex:index];
}

- (NSArray *)arrayOfWheels
{
    return [_mutableArrayOfWheels copy];
}

- (void)acceptComponentVisitor:(id<NimoComponentVisitor>) visitor
{
    [_engine acceptComponentVisitor:visitor];
    for (NimoWheel *wheel in self.arrayOfWheels) {
        [wheel acceptComponentVisitor:visitor];
    }
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"My car: %@", [NSDictionary dictionaryWithObjects:@[_engine, self.arrayOfWheels] forKeys:@[@"Engine", @"Wheels"]]];
}

@end

我们在类中添加了-(void)acceptComponentVisitor:(id<NimoComponentVisitor>)visitor接口,同意实现了访问者协议的visitor访问。(我家大门常打开,啦啦啦啦啦)

让我们来看下第一位访问者是谁?刚刚上面我们有提到一个需求,想对汽车各组件进行全面升级。那么就让这位专业的访问者来做吧!

定义具体访问者:此访问者具备升级汽车各组件的能力

//
//  NimoComponentUpgrade.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@interface NimoComponentUpgrade : NSObject <NimoComponentVisitor>

- (void) visitEngine:(NimoEngine *) engine;
- (void) visitWheel:(NimoWheel *) wheel;

@end
//
//  NimoComponentUpgrade.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoComponentUpgrade.h"

@implementation NimoComponentUpgrade

- (void) visitEngine:(NimoEngine *) engine
{
    NSLog(@"我是升级人员,正在对引擎<%@>进行升级", engine);
}

- (void) visitWheel:(NimoWheel *) wheel
{
    NSLog(@"我是升级人员,正在对车轮<%@>进行升级", wheel);
}

@end

让我们来看看这位访问者的工作能力如何

//
//  main.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoCar.h"
#import "NimoEngine.h"
#import "NimoWheel.h"
#import "NimoComponentMaintenance.h"
#import "NimoComponentUpgrade.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        NimoCar *car = [[NimoCar alloc] init];
        NimoEngine *engine = [[NimoEngine alloc] initWithModelName:@"V8"];
        NimoWheel *wheelA = [[NimoWheel alloc] init];
        NimoWheel *wheelB = [[NimoWheel alloc] init];
        NimoWheel *wheelC = [[NimoWheel alloc] init];
        NimoWheel *wheelD = [[NimoWheel alloc] init];
        
        car.engine = engine;
        [car addWheel:wheelA atIndex:0];
        [car addWheel:wheelB atIndex:1];
        [car addWheel:wheelC atIndex:2];
        [car addWheel:wheelD atIndex:3];
        
        NSLog(@"%@", car);
        
        //对组建进行“升级”
        NimoComponentUpgrade *upgradeVisitor = [[NimoComponentUpgrade alloc] init];
        [car acceptComponentVisitor:upgradeVisitor];
    }
    return 0;
}

看来这位访问者的工作很出色。

如果我们还需要对汽车各组件进行维修呢?那就定义一个专职维修的访问者

//
//  NimoComponentMaintenance.h
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NimoComponentVisitor.h"

@interface NimoComponentMaintenance : NSObject <NimoComponentVisitor>

- (void) visitEngine:(NimoEngine *) engine;
- (void) visitWheel:(NimoWheel *) wheel;

@end
//
//  NimoComponentMaintenance.m
//  VisitorDemo
//
//  Created by fu zheng on 15/8/12.
//  Copyright (c) 2015年 FuZheng. All rights reserved.
//

#import "NimoComponentMaintenance.h"

@implementation NimoComponentMaintenance

- (void) visitEngine:(NimoEngine *) engine
{
    NSLog(@"我是维修人员,正在对引擎<%@>进行维修", engine);
}

- (void) visitWheel:(NimoWheel *) wheel
{
    NSLog(@"我是维修人员,正在对车轮<%@>进行维修", wheel);
}

@end
//main.m
        ...
        //对组建进行“维修”
        NimoComponentMaintenance *maintenanceVisitor = [[NimoComponentMaintenance alloc] init];
        [car acceptComponentVisitor:maintenanceVisitor];
        ...

使用访问者模式后,添加操作,只需实现具体的访问者,不会对类的结构造成破坏。

时间: 2024-10-14 06:46:23

iOS设计模式---访问者模式的相关文章

.NET设计模式访问者模式

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它.2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口.3.Element 定义一个接受访问操作(accept

[我的设计模式] 访问者模式

访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式. 定义(源于GoF<Design Pattern>):表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法. 应用场景 用户访问博客.[我的设计模式] 访问者模式

【C#设计模式-访问者模式】

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口. 3.Element 定义一个接受访问操作(acce

最复杂的设计模式---访问者模式

今天,我们一起来探讨最后一个.最复杂的设计模式 访问者模式:它表示一个作用于某个对象结构中的各个元素的操作.它使你可以在不改变个元素的类前提下,定义作用于这些元素的新操作.这个地方要注意:1.需要有个对象结构类用于存储循环遍历的方法的方式:2.访问者模式是对元素的操作:3.可以任意添加对这些元素的新操作.确实有点复杂,我们先看看其结构图: 代码部分: Visitor类抽象声明了对各种类型元素的访问方法: abstract class Visitor { public abstract void

C#设计模式-访问者模式

一.访问者模式介绍 1.1 访问者模式的定义 表示一个作用于某对象结构中的各个元素的操作.它使你可以在不改变各个元素的类的前提下定义作用于这些元素的新操作. 1.2 访问者模式的结构图 具体的访问者模式结构图如下所示. 这里需要明确一点:访问者模式中具体访问者的数目和具体节点的数目没有任何关系.从访问者的结构图可以看出,访问者模式涉及以下几类角色. 抽象访问者角色(Vistor):声明一个活多个访问操作,使得所有具体访问者必须实现的接口. 具体访问者角色(ConcreteVistor):实现抽象

小菜学设计模式——访问者模式

背景 最后一个设计模式,也是<大话设计模式>公认最难的设计模式,当然不是理解上困难,我觉得应该是使用上困难,这个设计模式虽然具有非常良好的扩展能力,但却需要类的结构早早定义清晰,试想,需求时刻变化,你的类可以稳定吗? 1.使用意图 容易扩展,满足开发封闭原则 2.生活实例 男人和女人的状态,把ConcreteElmentA看成男人,把ConcreteElementB看成女人,那么,所有的Visitor实例就是成功状态.失败状态.结婚状态.升职状态等.把这些状态放在客户端的集合中维护,一旦需要,

PHP设计模式——访问者模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 访问者模式表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: 角色: 1.抽象访问者(State):为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.具体访问者(Success):实现访问者声明的接口. 3.抽象元素(Person):定义一个接受访问操

深入浅出设计模式——访问者模式(Visitor Pattern)

模式动机 对于系统中的某些对象,它们存储在同一个集合中,且具有不同的类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,而且不同的访问者其访问方式有所不同,访问者模式为解决这类问题而诞生.在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式.而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求.此时,访问者模式就是一个值得考虑的解决方案.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这

C++设计模式——访问者模式

访问者模式 在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化.该模式的目的是要把处理从数据结构分离出来.访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者.访问者模式将有关的行为集中到一个访问者对象中.现在再来说说我之前经历过的那个项目. 是基于Wi