iOS设计模式:工厂方法

原文地址:http://www.cocoachina.com/newbie/basic/2013/0516/6219.html

1、什么是工厂方法

GOF是这样描述工厂模式的:
“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”
 
在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。
工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好地符合了开放封闭原则。工厂方法也叫做虚构造器(Virtual Constructor)
如下图所示,是工厂方法的类结构图:

2、什么时候使用工厂方法

当是如下情况是,可以使用工厂方法:一个类不知道它所必须创建的对象的类时,一个类希望有它的子类决定所创建的对象时。
更多关于工厂方法的介绍,可以参考本文最后给出的参考内容。下面我们就来看看在iOS中工厂方法的一种实现方法。
 
iOS中工厂方法的实现
如下有一个类图,该图描述了下面即将实现的工厂方法(利用工厂方法,创建出不同的形状)。其中BVShapeFactory为工厂方法的基类,BVShape为形状的基类,BVClient通过BVShapeFactory,利用 BVShapeFactory的子类(BVCircleShapeFactory和BVSquareShapeFactory)分别创建出BVCircleShape和BVSquareShape。

如下图,是在Xcode中创建的相关文件

1.创建一个形状基类BVShape。该类中定义了形状的基本行为和属性,如下代码所示:
//
//  BVShape.h
//  FactoryMethodPattern
//
//  Created by BeyondVincent on 13-5-15.
//  Copyright (c) 2013年 BeyondVincent. All rights reserved.
//

#define BV_Exception_Format @"在%@的子类中必须override:%@方法"

@interface BVShape : NSObject

@property (nonatomic, weak)NSString *name;

// 子类必须重写这个draw方法,否则会抛出异常错误
-(void)draw;

@end

#import "BVShape.h"


@implementation BVShape

-(id)init
{
   self = [super init];
    if (self) {
        // 做一些初始化任务
    }
    return self;
}

-(void)draw
{
    // 如果是通过BVShape的实例调用此处的draw,则绘制一个BVShape图形
    if ([self isMemberOfClass:[BVShape class]]) {
        NSLog(@"绘制一个BVShape图形");
    } else {
        // 如果是通过BVShape子类的实例调用了此处的draw,则抛出一个异常:表明子类并没有重写draw方法。
        // 注:在OC中并没有abstract class的概念,只有protocol,如果在基类中只定义接口(没有具体方法的实现),
        //    则可以使用protocol,这样会更方便。 
        [NSException raise:NSInternalInconsistencyException
                    format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
    }
}

@end

在上面的代码中定义了一个draw方法,为了让子类必须实现该方法,在BVShape中做了特殊处理,具体内容可以看上面的代码,已经有注视了。
 
2.子类化形状基类。首先子类化一个圆形类:BVCircleShape。
#import "BVShape.h"

@interface BVCircleShape : BVShape

@end

#import "BVCircleShape.h"

@implementation BVCircleShape

-(void)draw
{
    NSLog(@"绘制一个BVCircleShape图形");
}

@end

在上面的子类中,重写了基类的draw方法。同样,我们再子类化一个正方形类,并重写draw方法,如下代码所示:

#import "BVShape.h"

@interface BVSquareShape : BVShape

@end

#import "BVSquareShape.h"

@implementation BVSquareShape

-(void)draw
{
    NSLog(@"绘制一个BVSquareShape图形");
}

@end

3.创建一个工厂方法的基类BVShapeFactory
#import "BVShape.h"

@interface BVShapeFactory : NSObject

-(BVShape *) factoryMethod;

@end

#import "BVShapeFactory.h"

@implementation BVShapeFactory

-(BVShape *)factoryMethod
{
    // 在此处,子类必须重写factoryMethod方法。当然,在工厂模式中,也可以在此处返回一个默认的Product。
    // 如果是通过BVShapeFactory子类的实例调用了此处的factoryMethod,则抛出一个异常:表明子类并没有重写factoryMethod方法。
    [NSException raise:NSInternalInconsistencyException
                format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
    
    // 下面这个return语句只是为了消除警告,实际上永远都不会执行到这里。
    return nil;
}

@end

在上面的代码中,定义了一个factoryMethod,该类的子类必须实现该方法,通过实现该方法,返回一个具体的形状对象。下面来看看该类的子类化。
 
4.子类化工厂方法的基类。首先子类化一个圆形工厂方法BVCircleShapeFactory:
#import "BVShapeFactory.h"
#import "BVCircleShape.h"

@interface BVCircleShapeFactory : BVShapeFactory

@end

@implementation BVCircleShapeFactory

-(BVShape *)factoryMethod
{
    return [[BVCircleShape alloc] init];
}

@end

如上代码所示,重写了factoryMethod,返回一个BVCircleShape实例。下面来看看另外一个子类BVSquareShapeFactory
#import "BVShapeFactory.h"
#import "BVSquareShape.h"

@interface BVSquareShapeFactory : BVShapeFactory

@end

#import "BVSquareShapeFactory.h"

@implementation BVSquareShapeFactory

-(BVShape *)factoryMethod
{
    return [[BVSquareShape alloc] init];
}

@end

该子类返回的是一个BVSquareShape实例。
 
5.工厂方法的使用。定义一个BVClient类,在该类中演示工厂方法的使用。代码如下:
@interface BVClient : NSObject

-(void)doSomething;

@end

#import "BVClient.h"

#import "BVShapeFactory.h"
#import "BVCircleShapeFactory.h"
#import "BVSquareShapeFactory.h"

#import "BVShape.h"
#import "BVCircleShape.h"
#import "BVSquareShape.h"

@implementation BVClient

-(void)doSomething
{
    // 工厂方法的实例化
    BVShapeFactory *circleShapefactory = [[BVCircleShapeFactory alloc] init];
    BVShapeFactory *squareShapefactory = [[BVSquareShapeFactory alloc] init];
    
    // 通过工厂方法实例化对应的形状
    BVShape *circleShape = [circleShapefactory factoryMethod];
    BVShape *squareShape = [squareShapefactory factoryMethod];
    
    // 调用形状的方法
    [circleShape draw];
    [squareShape draw];
}

@end




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值