面试其他程序员

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

2016-09-23  本文已影响1336人  栈溢出

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

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


简单工厂模式

是什么

简单工厂模式是属于创建型模式,又叫做静态工厂方法(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

为什么

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


工厂模式

是什么

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

简单工厂模式

怎么用

第二年:生意越做越大,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,跑车等等,那只能在工厂里写个各种逻辑判断,好吧,又违反了开闭原则,又回到类似简单工厂的弊端。这时候就需要用到抽象工厂模式。


抽象工厂模式

是什么

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


抽象工厂 产品族和等级结构示意图
  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)
上一篇 下一篇

猜你喜欢

热点阅读