那些你必须知道的设计模式之简单工厂模式,工厂模式,抽象工厂模式

哲学上说“是什么,为什么,怎么用”是认识问题的逻辑思维过程.

本文将以厂长工厂造车为例子讲述这三种设计模式。


简单工厂模式

是什么

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

简单工厂模式

简单工厂模式主要包含三部分:
工厂类角色:本模式核心,含有商业逻辑和判断逻辑,根据逻辑不同,生产具体的工厂产品。
抽象产品角色:定义了工厂方法创建的对象的接口。由接口或者抽象类来实现。
具体产品角色:工厂类所创建的对象就是此实例。由具体类实现。

怎么用

第一年:生意来了,老板就一个厂要造benz,audi的。

#import "CarSampleFactory.h"

@implementation CarSampleFactory
//    抽象产品就是具体产品的接口,直接用一句话代替了
-(void)createCarWithName:(NSString *)name {
    NSArray *car = @[@"Benz", @"BMW", @"Audi"];
    NSUInteger index  = [car indexOfObject:name];
    
    switch (index) {
        case 0:
            NSLog(@"生产了Benz具体产品(alloc你需要的类)");
            break;
        case 1:
            NSLog(@"生产了Audi具体产品");
            break;
        default:
            break;
    }
}
@end

为什么

  • 优点
    工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建的。所以也称之‘上帝类’。
  • 缺点
    由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中。每增加一种品牌的车子,都要修改逻辑判断处代码。不符合开闭原则,。

这些缺点在工厂方法模式中得到了一定的克服。


工厂模式

是什么

工厂方法模式是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。

简单工厂模式
  • 抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口或者继承
  • 具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
  • 抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
  • 具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。(benz车)

怎么用

第二年:生意越做越大,Audi啊来了,厂子忙不过了。聪明的厂长又开了三个厂子,并且叫了一个管理者(抽象工厂)来管理这些工厂。

#import "ViewController.h"

//    工厂方法
//  第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。

    BMWFactory *BMWF = [[BMWFactory alloc] init];
    [BMWF CreateCarBMW];
    
//  第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的(类似多态)
    CarAbstractFactory *caf = [[BMWFactory alloc] init];
    [caf CreateCarFactoy];
    
    caf = [[BenzFactory alloc] init];
    [caf CreateCarFactoy];
#import "CarAbstractFactory.h"

@implementation CarAbstractFactory
//抽象工厂
-(void)CreateCarFactoye{
    
}
@end

#import "BenzFactory.h"
//具体工厂
@implementation BenzFactory
-(void)CreateCarFactoy{
    [self CreateCarBenz];
}

- (void)CreateCarBenz{
//具体产品
    NSLog(@"工厂方法生产了Benz具体产品(alloc你需要的类)");
}
@end
#import "BMWFactory.h"

@implementation BMWFactory
-(void)CreateCarFactoy{
    [self CreateCarBMW];
    
}
- (void)CreateCarBMW{
    NSLog(@"工厂方法生产了BMW具体产品(alloc你需要的类)");
}
@end
#import "AudiFactory.h"

@implementation AudiFactory
-(void)CreateCarFactoy{
    [self CreateCarAudi];
}
- (void)CreateCarAudi{
    NSLog(@"工厂方法生产了Benz具体产品(alloc你需要的类)");
}
@end

为什么

  • 优点
    工厂方法模式是简单工厂模式的衍生,相当于横向扩展。当有新的产品(法拉利汽车),只要新建继承抽象工厂的类就好了。完全符合继承原则。

  • 缺点
    但是产品种类特别多的时候,就会产生大量的工厂类。所以对于类似的产品我们还是用简单工厂来实现。复杂的业务逻辑可以使用两者结合的模式。开发者依照自身取舍。

可是benz和audi等工厂突然又想生产自己suv,跑车等等,那只能在工厂里写个各种逻辑判断,好吧,又违反了开闭原则,又回到类似简单工厂的弊端。这时候就需要用到抽象工厂模式。


抽象工厂模式

是什么

是工厂方法设计模式的一种扩展。当有多个抽象角色时,使用的一种工厂模式。


抽象工厂
  • AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
  • AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
  • ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
产品族和等级结构示意图
  1. 产品等级结构:产品等级结构即产品的继承结构(三种品牌汽车构成了三个不同的产品等级结构)
  2. 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如(suv工厂里生产的三个品牌车型)

怎么用

第三年:audi,benz,bmw告诉厂长,我们这次的订单需要分成suv,business,sport三种类型的车。这时候管理蛮不过来了。所以厂子又请了两个管理。分别管理三个品牌的车子。

//  抽象工厂两种情况同工厂方法上
//  method 1
    SUVFactory *suvf = [[SUVFactory alloc] init];
    [suvf createAudiCar];
    
//  method 2
    AbstractFactorys *af = [[SportsFactorys alloc] init];
    [af CreateAudiFactoy];
#import <Foundation/Foundation.h>

@interface AbstractFactorys : NSObject
//抽象工厂(三个管理者)
-(void)CreateBenzFactoy;
-(void)CreateBMWFactoy;
-(void)CreateAudiFactoy;
@end
#import "SUVFactory.h"
//具体工厂
@implementation SUVFactory
-(void)createBenzCar{
    NSLog(@"抽象工厂方法生产了benzSUV");
}
-(void)createBWMCar{
    NSLog(@"抽象工厂方法生产了BWMSUV");
}
-(void)createAudiCar{
    NSLog(@"抽象工厂方法生产了AudiSUV");
}
@end

为什么

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率,如使用工厂方法模式,上图所示结构需要提供15个具体工厂,而使用抽象工厂模式只需要提供3个具体工厂。

当增加新的产品族的时候,符合“开闭原则”,只需让产品继承相应的抽象产品,对象的工厂继承抽象工厂即可,而无需修改其他的代码。

当增加产品等级结构的时候,不符合“开闭原则”,如新添加大众,那么在soprt,suv,business三个具体工厂里面都进行修改。当然我们可以配合反射机制来对抽象工厂进行优化。

//根据字符串来创建类
    NSClassFromString(<#NSString * _Nonnull aClassName#>)```
----

###总结

简单工厂启示是工厂方法的一种极端实现,工厂方法是抽象方法的一种极端实现。在实际项目中,如果不是项目过大或者功能过于复杂,抽象工厂设计模式一般使用不到。简单工厂模式反而是用的比较频繁。但是这种思想我们还是需要借鉴的。在CoCoa Touch框架中的'类簇'便是基于抽象工厂模式设计。NSNumber就是最好的例子。
NSNumber *boolNumber = [NSNumber numberWithBool:YES];
NSLog(@"%@",[[boolNumber class] description]);

// 输出 __NSCFBoolean
NSLog(@"%d",[boolNumber boolValue]);
//输出1
NSNumber(抽象工厂)->NSCFBoolean(具体工厂子类)-> 重载boolValue工厂方法 ->返回实际产品

这种设计多类型的对象的创建。好的模式应该是变成一种抽象,不暴露创建过程中任何不必要的细节和创建对象的具体类型。



ps:最后厂长去打lol了

都看到最后了还不给个喜欢么……

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

推荐阅读更多精彩内容