【iOS类簇】工厂设计模式(Class Cluster)

摘要软件的设计模式如同高楼的设计蓝图,优秀巧妙应用设计模式可以使编码者更加轻松,软件的架构也会更加合理,这篇博客主要探讨工厂设计模式,iOS中的类簇,就是工厂模式的一种实现。

工厂设计模式的探讨——iOS类簇的应用分析

一、何为设计模式

什么是设计模式,先来看段度娘的话:
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

其实我们不需要这么专业,在我的理解,设计模式就是一种规范化的编程习惯,养成了这样的思想与习惯,对我们的代码,总是有好处了。

二、工厂设计模式

首先,工厂设计模式是创建对象的一种设计模式,一个严格意义上的工厂设计模式应该是一个纯虚的构造方法。由子类进行具体对象的创建,我们可以这样理解:现在有一个珲少牌制造工厂,这个工厂可以制造多种交通工具,我大胆一些,假设它可以制造飞机,轮船。小汽车,公交车,出租出和自行车,那么,这些不同的车种虽然功能和大类别统一,但是他们的个体差异也是天地之别,就比如我飞机一小时可以飞5000公里,自行车拼死了劲也不一定能骑20公里。所以,如果珲少这个大工厂要生产他们,也不可能把他们放在一起生产。一个比较明智的决定是,开立分厂,比如珲少飞机工厂专门生产飞机,珲少自行车工厂专门生产自行车。
好了,如果将我们这种人类世界的思维运用于程序世界,那么我们可以通过工厂的这种思维方式来将一些大类抽象为工厂,通过定义接口或者说是定义虚函数来规范这个大工厂的生产规模和流程,由其子类来具体实现这些方法,也就是由一个个小的分厂来明确的生产我们需要的东西。这就是工厂设计模式的基本思路。

三、工厂的设计模式有什么用

许多开发者或许并不在意设计模式这个东西,我们可能会想,我实现我的功能就可以了,你管我怎么设计呢。在这篇博客的开头就说到,在我理解中,设计模式就是一种编程习惯和规范,更是一种众多开发者摸索出来的经验,这就像农业上的套种间种和你随便种,哪一种效率高,收成好,不言而喻。那么在软件设计中,工厂模式的应用在哪呢?
我们先来体验一下在iOS开发中,一些使用工厂设计模式的系统类为我们带来的便捷之处:
1、认识一个名词 类簇
在iOS的Foundation框架中,类簇是一种常用的设计模式,他将一些相近的,私有的,具体的子类组合在一个实体的抽象类下面,我称这个抽象类为实体的,是因为和我们交互的接口承载者,就是这个抽象大类。我们平时常用的三大类,NSString,NSArray,NSDictionary都是类簇,我们通过他们创建的对象都是其子类对象的实例化,并不是他本身的实例化,我们还通过上面的例子来理解,我买了一辆珲少小汽车,这两汽车的生产实际是在珲少汽车工厂生产的,但是我个人会依然认为,这是珲少工厂出产的汽车。我们可以通过打印类名来验证:
NSString * str = [[NSString alloc]initWithCString:"2" encoding:0]; NSLog(@"%@",[str class]);

结果如下:



可以看到,真实的对象是NSString的子类__NSCFString进行实例化的。
2.这样设计的优势在哪
如果你通过NSString的事例还是无法体会到类簇,也就是工厂设计模式的优势,那么下面这个例子你一定经常遇到:NSNumber。我们在创建数字对象的时候,通常会这样考虑,如果是int值,我需要一个IntNumber的类,float值,我需要一个FloatNumber类,如果foundation框架真这么设计的话,那么你现在就痛苦了,你不仅要记住好多这样相似的类,调用方法时也要相应的对象调其内的方法,这使开发者的开发变得更加繁琐,并且对于开发者来说,我并不需要知道具体我创建了什么类,我只是想让他完成既定的方法。说的更通俗一点,还是上面的制造工厂,使用者并不在乎具体这个交通工具是哪个地方生产出来的,只要它价钱和速度都是使用者预期的结果就好了。
3.工厂设计模式的应用
通过上面的分析,我们大致可以总结出工厂这种设计模式的应用场景:
(1)当一个类并不知道要创建的具体对象是什么,交由子类处理
(2)当一些类有相似的行为和结构,只是具体实现不同时,可以抽象出工厂
(3)使用者并不在乎具体类型,只在乎接口约定的行为,并且这种行为有个体差异

四、在iOS中模拟一个工厂

同样是上面的例子,我们来用代码模拟一下:
首先,我们创建一个抽象的工程类,在其中创建一些私有的子类:

#import <Foundation/Foundation.h>//交通工具的枚举
typedef enum {car,boat,airport,bycicle,bus,taxi}ToolsName;
  //代理
@protocol TransPortationDelegate <NSObject>
-(void)toHome:(Class)class;
@end
//抽象工厂类
@interface TramsPortationFactory : NSObject
+(TramsPortationFactory*)buyTool:(ToolsName)tool;//共有的方法接口
-(int)shouldPayMoney;
-(void)run;
@property(nonatomic,strong)id<TransPortationDelegate>delegate;
@end

//具体实现的子类(新建文件)
@interface CarFactory : TramsPortationFactory
@end

@interface BoatFactory : TramsPortationFactory
@end

@interface AirportFactory : TramsPortationFactory
@end

@interface BycicleFactory : TramsPortationFactory
@end

@interface TaxiFactory : TramsPortationFactory
@end

@interface BusFactory : TramsPortationFactory
@end

实现文件如下:

#import "TramsPortationFactory.h"
#impor "CarFactory.h"
//引入所有私有子类的头文件
@implementation TramsPortationFactory//实现的创建方法
+(TramsPortationFactory*)buyTool:(ToolsName)tool{ 
   switch (tool) {       
       case car:            
          return [[CarFactory alloc]init];
          break;
       case airport: 
           return [[AirportFactory alloc]init];
           break; 
       case bycicle: 
           return [[BycicleFactory alloc]init]; 
           break;
       case boat:  
           return [[BoatFactory alloc]init];  
            break; 
       case taxi:
            return [[TaxiFactory alloc]init];  
            break; 
       case bus: 
             return [[BusFactory alloc]init];
            break; 
       default: 
             break;    }
}
-(int)shouldPayMoney{ 
   return 0;
}
-(void)run{ 
   [self.delegate toHome:[self class]];
}
@end

//各自类实现具体的行为
@implementation CarFactory
-(int)shouldPayMoney{   
 return 50;
}
-(void)run{
    [super run];
    NSLog(@"car to home");
}
@end

@implementation AirportFactory
-(int)shouldPayMoney{
    return 1000;
}
-(void)run{
    [super run];
    NSLog(@"fly to home");
}
@end

@implementation BoatFactory
-(int)shouldPayMoney{
    return 300;
}
-(void)run{
    [super run];
    NSLog(@"boat to home");
}
@end

@implementation BusFactory
-(int)shouldPayMoney{
    return 10;
}
-(void)run{
    [super run];
    NSLog(@"bus to home");
}
@end

@implementation BycicleFactory
-(int)shouldPayMoney{
    return 0;
}
-(void)run{ 
   [super run];
    NSLog(@"run to home");
}
@end

@implementation TaxiFactory
-(int)shouldPayMoney{
    return 100;
}
-(void)run{
    [super run];
    NSLog(@"go to home");
}
@end

这样,我们的一个生产工厂就完成了,在外面,我们只需要知道一个类,我们的抽象父类,就可以实现个子类的行为,示例如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    TramsPortationFactory * tool = [TramsPortationFactory buyTool:car]; 
   tool.delegate=self;
    [tool run];//成员关系从属于CarFactory类,所以调用CarFactory类中的run方法
    NSLog(@"花了:%d钱",[tool shouldPayMoney]);
    TramsPortationFactory * tool2 = [TramsPortationFactory buyTool:airport]; 
   tool2.delegate=self; 
   [tool2 run]; 
   NSLog(@"花了:%d钱",[tool2 shouldPayMoney]);
 }
-(void)toHome:(Class)class{
    NSLog(@"%@",NSStringFromClass(class));
}


可以看到,对于开发者,我们并不知晓CarFactory类的存在,我们只需要通过TramsPortationFactory类,就能够操作各种交通工具,达到我们的需求。

综上所述:

工厂设计模式,即使用类簇的概念,创建一个抽象的公共类,创建多个继承自该抽象公共类的子类,由子类实现不同的功能,然后将子类引入到父类,即抽象公共类的.m实现文件中,通过父类调用特定方法实例化子类,进一步调用子类的实现方法,可以很好地隐藏子类的接口及实现方式。注意,子类接口和实现不能直接写入到父类文件中,会暴漏子类接口给外界,所以子类文件需要重新创建,并引入到父类.m中隐藏或打包成静态库由抽象公共类统一调用管理。

文章出处

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

推荐阅读更多精彩内容

  • 简单工厂模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一般是alloc一个对象,如果需要创建...
    GitHubPorter阅读 8,024评论 6 16
  • 抽象工厂模式 介绍 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式...
    666真666阅读 1,171评论 0 7
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,820评论 1 15
  • 一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者...
    RamboLI阅读 703评论 0 1
  • 1.求而不得本就是人生常态 我有个朋友小宋姑娘一直梦想成为一名老师,并且一直为之努力。 上个月,到了查询成绩的那一...
    苏小鹿lu阅读 2,727评论 4 9