DP之工厂模式

今天我们来看看工厂的一系列模式
简单工厂模式 - 工厂模式 - 抽象工厂模式

一个引子:

在OC开发中,我们已经知道常见的两段式对象创建法,[[SomeClass alloc]init],
有时,我们已经注意到有一些“便利”方法返回类的实例。例如我们的NSNumber 类,
 通过类方法numberWith****方法创建NSNumber对象。比如,我们可以向NSNumber
 发送[NSNumber numberWithBool:bool],以获得与传入参数同类型的各种NSNumber实例。与如何创建NSNumber的具体子类型的实例有关的所有细节,都由NSNumber的类
 工厂方法负责。仔细想想,我们有没有看到具体的创建过程,具体子类是什么?[NSNumber numberWithBool:bool]的情况是,方法接受值bool,并把NSNumber的
 内部子类的一个实例初始化,让他能够反映传入的值bool。

@interface NSNumber (NSNumberCreation)

+ (NSNumber *)numberWithChar:(char)value;
+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
+ (NSNumber *)numberWithShort:(short)value;
+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
+ (NSNumber *)numberWithInt:(int)value;
+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
+ (NSNumber *)numberWithLong:(long)value;
+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
+ (NSNumber *)numberWithLongLong:(long long)value;
+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
+ (NSNumber *)numberWithFloat:(float)value;
+ (NSNumber *)numberWithDouble:(double)value;
+ (NSNumber *)numberWithBool:(BOOL)value;
+ (NSNumber *)numberWithInteger:(NSInteger)value NS_AVAILABLE(10_5, 2_0);
+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value NS_AVAILABLE(10_5, 2_0);

@end

简单工厂模式

1.什么是简单工厂模式

简单工厂模式属于类的创建型模式,又叫静态工厂方法模式。通过专门一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

2.模式中包含的角色以及其职责

  1. 工厂角色:
    简单工厂模式的核心,他负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
  2. 抽象角色:
    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  3. 具体产品角色:
    简单工厂模式所创建的具体实例对象。

// 依赖关系: 一个类的对象,当另一个类的函数参数或者 是返回值。

3.简单工厂的优缺点

在这个设计模式中,工厂类是整个模式的关键所在。在包含必要的逻辑判断,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户 在使用时可以直接根据工厂类去创建所需的实例,而无需了解谢谢对象是如何创建以及如何组织的,有利于整个软件体系结构的优化,不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以,高内聚方面做得并不好,另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。

talk is cheap, Show me the code.

#import <Foundation/Foundation.h>
typedef enum FruitType
{
    BananaType,
    PearType,
    AppleType
}FruitType;

@interface Fruit : NSObject
- (void) getFruit;
@end
@implementation Fruit
- (void) getFruit{

}
@end

@interface Banana : Fruit
- (void) getFruit;

@end
@implementation Banana

- (void) getFruit
{
    NSLog(@"香蕉");
}
@end
@interface Pear : Fruit
- (void) getFruit;

@end
@implementation Pear

- (void) getFruit
{
    NSLog(@"梨子");
}
@end
@interface Apple : Fruit
- (void) getFruit;

@end
@implementation Apple

- (void) getFruit
{
    NSLog(@"苹果");
}
@end


@interface Factory : NSObject

+ (Fruit *)CreteFruit:(FruitType) type;

@end
@implementation Factory
+ (Fruit *)CreteFruit:(FruitType) type
{
    if(type == BananaType)
    {
        return [Banana new];
    }
    if(type == PearType)
    {
        return [Pear new];
    }
    if(type == AppleType)
    {
        return [Apple new];
    }
    return NULL;
}

@end

int main(int argc, const char * argv[]) {
    Fruit *fruit1 = [Factory CreteFruit:AppleType];
    [fruit1 getFruit];
    Fruit *fruit2 =[Factory CreteFruit:BananaType];
    [fruit2 getFruit];
    return 0;
}

// 简单工厂主要用于创建对象,新添加类时,不会影响以前的系统代码。核心思想是用一个工厂来根据输入的条件产生不同的类,然后根据不同类的函数得到不同的结果。

优点:适用于不同情况创建不同的类。
缺点:客户端必须要知道基类和工厂类,耦合性太差,你可以把客户端当做main函数,也就是调用创建的地方。

工厂模式

1.概念:

工厂方法模式同样属于类的创建模式,又被称为多态工厂模式。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

2.类图角色和职责

抽象工厂(Creator)角色
工厂方法模式的核心,任何工厂类都必须实现这个接口。

具体工厂( Concrete Creator)角色
具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

抽象(Product)角色
工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

具体产品(Concrete Product)角色
工厂方法模式所创建的具体实例对象

3.工厂方法模式和简单工厂模式比较

工厂方法模式与简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

“开放-封闭”通过添加代码的方式,不是通过修改代码的方式完成功能的增强。

### talk is cheap, Show me the code.

#import <Foundation/Foundation.h>
@interface Fruit : NSObject
- (void) sayname;
@end
@implementation Fruit
- (void) sayname{
    
}
@end

@interface FruitFactory : NSObject
- (Fruit *) getFruit;
@end
@implementation FruitFactory
- (Fruit *) getFruit{
    
    return  [Fruit new];
}
@end


@interface Banana : Fruit
- (void) sayname;
@end
@implementation Banana
- (void) sayname{
    NSLog(@"Banana \n");
}
@end

@interface BananaFactory : FruitFactory
- (Fruit *) getFruit;
@end
@implementation BananaFactory
- (Fruit *) getFruit{
    return  [Banana new];
}
@end

@interface Apple : Fruit
- (void) sayname;
@end

@implementation Apple
- (void) sayname{
    NSLog(@"Apple \n");
}
@end

@interface AppleFactory : FruitFactory
- (Fruit *) getFruit;
@end

@implementation AppleFactory
- (Fruit *) getFruit{
    
    return  [Apple new];
}

@end

int main()
{
    
    FruitFactory *ff = NULL;
    Fruit *fruit = NULL;
    
    ff = [BananaFactory new];
    fruit = [ff getFruit];
    [fruit sayname];
    
    // 苹果
    ff = [AppleFactory new];
    fruit = [ff getFruit];
    [fruit sayname];
    
    return 0;
}

发现了,设计模式就是让简单的代码复杂化。但是当我们搭好了这样的框架,后期的维护和扩展,简直就像是在做配置一样,随手就来。

抽象工厂

1.概念:

抽象工厂模式是所有形态的工厂模式中最为抽象的。抽象工厂模型可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

2.注解:

工厂模式:要么生产香蕉、要么生产苹果、要么生产西红柿;但是不能同时生产一个产品组。
抽象工厂:能同时生产一个产品族。这就是抽象工厂存在原因

解释:
具体工厂在开闭原则下,​​能生产香蕉/苹果/梨子;
​抽象工厂:在开闭原则下,​​能生产:南方香蕉/苹果/梨子 (产品族) ​​​​​​​​​​北方香蕉/苹果/梨子

重要区别
工厂模式只能生产一个产品。(要么香蕉、要么苹果)
抽象工厂可以一下生产一个产品族(里面有很多产品组成)

3.模式中包含的角色及其职责

  1. 抽象工厂(Creator)角色
    抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

  2. 具体工厂( Concrete Creator)角色
    具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。

  3. 抽象(Product)角色
    抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

  4. 具体产品(Concrete Product)角色
    抽象模式所创建的具体实例对象

talk is cheap, Show me the code.

#import <Foundation/Foundation.h>
@interface Fruit : NSObject
- (void) sayname;
@end
@implementation Fruit
- (void) sayname{
    
}
@end

@interface FruitFactory : NSObject
- (Fruit *) getApple;
- (Fruit *) getBanana;

@end
@implementation FruitFactory
- (Fruit *) getApple{
    
    return  [Fruit new];
}
- (Fruit *) getBanana{
    
    return  [Fruit new];
}
@end


@interface SouthBanana : Fruit
- (void) sayname;
@end
@implementation SouthBanana
- (void) sayname{
    NSLog(@"SouthBanana \n");
}
@end


@interface SouthApple : Fruit
- (void) sayname;
@end
@implementation SouthApple
- (void) sayname{
    NSLog(@"SouthApple \n");
}
@end


@interface NorthApple : Fruit
- (void) sayname;
@end
@implementation NorthApple
- (void) sayname{
    NSLog(@"NorthApple \n");
}
@end


@interface NorthBanana : Fruit
- (void) sayname;
@end
@implementation NorthBanana
- (void) sayname{
    NSLog(@"NorthBanana \n");
}
@end


@interface SourthFruitFactory : FruitFactory
- (Fruit *) getApple;
- (Fruit *) getBanana;

@end
@implementation SourthFruitFactory
- (Fruit *) getApple
{
    return [SouthApple new];
}
- (Fruit *) getBanana
{
    return [SouthBanana new];
}
@end

@interface NorthFruitFactory : FruitFactory
- (Fruit *) getApple;
- (Fruit *) getBanana;

@end
@implementation NorthFruitFactory
- (Fruit *) getApple
{
    return [NorthApple new];
}
- (Fruit *) getBanana
{
    return [NorthBanana new];
}
@end


int main()
{
    
    FruitFactory *ff = NULL;
    Fruit *fruit = NULL;
    
    ff = [SourthFruitFactory new];
    fruit = [ff getApple];
    [fruit sayname];
    fruit = [ff getBanana];
    [fruit sayname];

    // 苹果
    ff = [NorthFruitFactory new];
    fruit = [ff getBanana];
    [fruit sayname];
    fruit = [ff getApple];
    [fruit sayname];
    
    return 0;
}

理解概念是第一步,在日常开发中,如何其一反三的使用,需要多加练习和斟酌。

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

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,885评论 1 15
  • 一、工厂模式介绍 工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每...
    端木轩阅读 12,684评论 1 20
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • 在.h里面的 #import//标准颜色 #define kStyle_Color_按钮蓝 @"#1992f5" ...
    Kloar阅读 497评论 0 0
  • //text()没参数 获取文本 不能获取标签 覆盖原有的内容 //给元素设置新文本 //text...
    Simon_s阅读 163评论 0 0