引言
某手机厂与苹果公司签订了苹果手机加工协议,负责苹果手机的装配工作,工厂设在郑州。由于业务的扩展,又跟小米手机签订了加工协议,负责小米手机的装配工作,装配工厂设在武汉。此时,手机厂下属两个分厂分别进行着苹果手机和小米手机的生产作业。苹果手机厂会生产出苹果手机、苹果数据线和苹果耳机。小米手机厂会生产处小米手机、小米数据线和小米耳机。某一天你要去这个厂拿个样机,这时你碰到的是小米厂的负责人,他给你的是小米手机,你碰到的是苹果手机厂的负责人,那么他给你的是苹果手机。你无需知道工厂生产手机的每个细节,你只需要一个手机样品。
抽象工厂: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
抽象工厂与工厂方法
抽象工厂与工厂方法模式在许多方面都非常相似。很多人常常搞不清楚应该在什么时候用哪一个。两个模式都有相同的目的:创建对象而不让客户端知晓返回了什么确切的具体对象。下表为抽象工厂模式与工厂方法模式的对比:
抽象工厂 | 工厂方法 |
---|---|
通过对象组合创建抽象产品 | 通过类继承创建抽象产品 |
创建多系列产品 | 创建一种产品 |
必须修改父类的接口才能支持新的产品 | 子类化创建者并重载工厂方法以创建新产品 |
软件设计的黄金法则:变动需要抽象
如果有多个类共有相同的行为,但实际实现不同,则可能需要某种抽象类型作为其父类被继承。抽象类型定义所有相关具体类将共有的共同行为。例如,我们知道普通的手机是什么样子,在拿到样品的时候能预料到会拿到什么。我们说拿手机样品,这里手机是一个抽象类型,定义了手机应该具有的共同特征。但是,从不同的负责人哪里我们可以得到不同的手机,我们统称为“手机”。
因此,我们在产品和品牌上有几种变化,因此需要对全体进行某种抽象。需要两个手机工厂,各自会使用工厂方法生产手机、耳机和USB数据线。下图中的类图说明了他们的关系:
每个产品有自身的产品体系,并有各个具体工厂中的工厂方法支持。产品由两个不同的品牌工厂——TKXiaomiFactory
和TKiPhoneFactory
来“生产”。他们各自重载抽象TKMobileFactory
类中定义的工厂方法mobile
,headSet
和usbCable
,并根据工厂设计所针对的品牌返回具体产品。
超累的类方法factoryWithType
是根据具体类型返回TKMobileFactory
的正确版本的工厂方法。其子类不应重载这个方法(尽管子类能够这么做) factoryWithType
方法根据传入的类型返回一个具体品牌工厂的实例。在TKMobileFactory
中的这些工厂方法(mobile
,headSet
和usbCable
)的默认实现返回抽象产品TKMobileObject
,TKHeadSet
,TKUSBCable
的实例,不带任何品牌细节。每个品牌所要求的一切细节将由实际的具体品牌工厂在其重载的工厂方法中生产。
抽象工厂类
//
// TKMobileFactory.h
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import <Foundation/Foundation.h>
@class TKMobileObject;
@class TKHeadSet;
@class TKUSBCable;
typedef enum : NSUInteger {
MobileTypeXiaomi,
MobileTypeiPhone,
} MobileType;
/**
手机工厂
*/
@interface TKMobileFactory : NSObject
+ (TKMobileFactory *)factoryWithType:(MobileType)mobileType;
- (TKMobileObject *)mobile;
- (TKHeadSet *)headSet;
- (TKUSBCable *)usbCable;
@end
//
// TKMobileFactory.m
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import "TKMobileFactory.h"
#import "TKMobileObject.h"
#import "TKUSBCable.h"
#import "TKHeadSet.h"
#import "TKiPhoneFactory.h"
#import "TKXiaomiFactory.h"
@implementation TKMobileFactory
+ (TKMobileFactory *)factoryWithType:(MobileType)mobileType {
switch (mobileType) {
case MobileTypeXiaomi:
return [[TKXiaomiFactory alloc] init];
break;
case MobileTypeiPhone:
return [[TKiPhoneFactory alloc] init];
break;
default:
break;
}
}
- (TKMobileObject *)mobile {
return nil;
}
- (TKHeadSet *)headSet {
return nil;
}
- (TKUSBCable *)usbCable {
return nil;
}
@end
iPhone工厂类
//
// TKiPhoneFactory.h
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import "TKMobileFactory.h"
/**
iPhone 工厂
*/
@interface TKiPhoneFactory : TKMobileFactory
- (TKMobileObject *)mobile;
- (TKHeadSet *)headSet;
- (TKUSBCable *)usbCable;
@end
//
// TKiPhoneFactory.m
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import "TKiPhoneFactory.h"
#import "TKiPhoneObject.h"
#import "TKiPhoneHeadSet.h"
#import "TKiPhoneUSBCable.h"
@implementation TKiPhoneFactory
- (TKMobileObject *)mobile {
return [[TKiPhoneObject alloc] init];
}
- (TKHeadSet *)headSet {
return [[TKiPhoneHeadSet alloc] init];
}
- (TKUSBCable *)usbCable {
return [[TKiPhoneUSBCable alloc] init];
}
@end
小米工厂类
//
// TKXiaomiFactory.h
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import "TKMobileFactory.h"
/**
小米工厂
*/
@interface TKXiaomiFactory : TKMobileFactory
- (TKMobileObject *)mobile;
- (TKHeadSet *)headSet;
- (TKUSBCable *)usbCable;
@end
//
// TKXiaomiFactory.m
// DesignPattern-AbstractFactory
//
// Created by Evergrande-teki on 2019/4/12.
// Copyright © 2019年 Evergrande-teki. All rights reserved.
//
#import "TKXiaomiFactory.h"
#import "TKXiaomiObject.h"
#import "TKXiaomiHeadSet.h"
#import "TKXiaomiUSBCable.h"
@implementation TKXiaomiFactory
- (TKMobileObject *)mobile {
return [[TKXiaomiObject alloc] init];
}
- (TKHeadSet *)headSet {
return [[TKXiaomiHeadSet alloc] init];
}
- (TKUSBCable *)usbCable {
return [[TKXiaomiUSBCable alloc] init];
}
@end
参考资料:
《Object-C编程之道 iOS设计模式解析》
iOS 三种工厂模式(简单工厂模式、工厂模式、抽象工厂模式)
代码已上传Github,如有问题,欢迎指正。