工廠模式可以簡單概括為同類型不同型號的產(chǎn)品有各自對應(yīng)的工廠進行生產(chǎn)畸颅。
比如iPhone手機旗下有iPhoneX及iPhone8兩種型號的手機,iPhoneX有自己iPhoneX的專屬工廠進行生產(chǎn)逮栅,而iPhone8有自己iPhone8的專屬工廠進行生產(chǎn)。兩條生產(chǎn)線沒有交集互不影響驹闰,后期如果新增或廢棄相關(guān)類型的產(chǎn)品也不會影響到原有的生產(chǎn)線晨雳。
三種模式
簡單工廠模式:簡單工廠模式是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式紧卒,可以理解為是不同工廠模式的一個特殊實現(xiàn)侥衬。
工廠模式:抽象了工廠接口的具體產(chǎn)品,應(yīng)用程序的調(diào)用不同工廠創(chuàng)建不同產(chǎn)品對象跑芳。(抽象產(chǎn)品)
抽象工廠模式:在工廠模式的基礎(chǔ)上抽象了工廠轴总,應(yīng)用程序調(diào)用抽象的工廠發(fā)發(fā)創(chuàng)建不同產(chǎn)品對象。(抽象產(chǎn)品+抽象工廠)
一博个、簡單工廠模式
1怀樟、簡單工廠模式定義
? 簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實例盆佣,被創(chuàng)建的實例通常都具有共同的父類往堡。因為在簡單工廠模式中用于創(chuàng)建實例的方法是靜態(tài)(static)方法,因此簡單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式共耍,它屬于類創(chuàng)建型模式虑灰。
? 注意:簡單工廠模式并不屬于GoF 23個經(jīng)典設(shè)計模式,但通常將它作為學(xué)習(xí)其他工廠模式的基礎(chǔ)痹兜。
簡單工廠模式的要點:當(dāng)你需要什么瘩缆,只需要傳入一個正確的參數(shù),就可以獲取你所需要的對象佃蚜,而無須知道其創(chuàng)建細節(jié)。
2着绊、簡單工廠模式包含的角色
Factory(工廠角色):工廠角色即工廠類谐算,它是簡單工廠模式的核心,負責(zé)實現(xiàn)創(chuàng)建所有產(chǎn)品實例的內(nèi)部邏輯归露;工廠類可以被外界直接調(diào)用洲脂,創(chuàng)建所需的產(chǎn)品對象;在工廠類中提供了靜態(tài)的工廠方法factoryMethod(),它的返回類型為抽象產(chǎn)品類型Product恐锦。
Product(抽象產(chǎn)品角色):它是工廠類所創(chuàng)建的所有對象的父類往果,封裝了各種產(chǎn)品對象的公有方法,它的引入將提高系統(tǒng)的靈活性一铅,使得在工廠類中只需定義一個通用的工廠方法陕贮,因為所有創(chuàng)建的具體產(chǎn)品對象都是其子類對象。
ConcreteProduct(具體產(chǎn)品角色):它是簡單工廠模式的創(chuàng)建目標(biāo)潘飘,所有被創(chuàng)建的對象都充當(dāng)這個角色的某個具體類的實例肮之。每一個具體產(chǎn)品角色都繼承了抽象產(chǎn)品角色,需要實現(xiàn)在抽象產(chǎn)品中聲明的抽象方法卜录。
? 簡單工廠模式的要點:當(dāng)你需要什么戈擒,只需要傳入一個正確的參數(shù),就可以獲取你所需要的對象艰毒,而無須知道其創(chuàng)建細節(jié)筐高。
3、結(jié)構(gòu)圖
父類Fruits具有一個屬性name和一個方法sweet丑瞧、poorTaste柑土,AppleFruit和OrangeFruit繼承自Fruits,簡單工廠類為FruitFactory嗦篱,負責(zé)根據(jù)傳入的不同參數(shù)FruitType來決定生產(chǎn)的是AppleFruit還是OrangeFruit冰单。
4、示例
本Demo還是以小販賣蘋果和橘子為例:(小販就是一個工廠灸促,他為你提供蘋果诫欠,橘子等水果)
- 先創(chuàng)建Fruits水果類,有一個sweet()浴栽、poorTaste()抽象方法荒叼,表示抽象產(chǎn)品類;
- 然后創(chuàng)建AppleFruit和OrangeFruit類典鸡,繼承自Fruits類被廓,表示具體產(chǎn)品類;
- 然后創(chuàng)建FruitFactory工廠類萝玷,有一個fruitsFactory:type方法嫁乘,聲明但未實現(xiàn),表示抽象工廠球碉;
具體代碼如下:
Fruits類:
#import <Foundation/Foundation.h> //Fruits.h
@interface Fruits : NSObject
/**水果名*/
@property (nonatomic,copy) NSString *name;
- (void)sweet; /**< 甜 */
- (void)poorTaste; /**< 不好吃 */
@end
#import "Fruits.h" //Fruits.m
@implementation Fruits
// 甜
- (void)sweet {}
// 不好吃
- (void)poorTaste {}
@end
AppleFruit和OrangeFruit類
/*------------------AppleFruit------------------*/
#import "Fruits.h" //AppleFruit.h
//遵循了開閉原則
@interface AppleFruit : Fruits
- (void)freshApple; /**< 新鮮的蘋果 */ // 開閉原則
@end
#import "AppleFruit.h" //AppleFruit.m
@implementation AppleFruit
@synthesize name;
// 甜
- (void)sweet {
NSLog(@"%@非常甜的啦-----%s",self.name, __func__);
}
// 不好吃
- (void)poorTaste {
NSLog(@"%@不好吃的啦-----%s",self.name,__func__);
}
// 新鮮的蘋果
- (void)freshApple {
NSLog(@"%@是新鮮的-----%s",self.name,__func__);
}
@end
/*------------------OrangeFruit------------------*/
#import "Fruits.h" //OrangeFruit.h
@interface OrangeFruit : Fruits
- (void)acidOrange; /**< 酸橘子 */
@end
#import "OrangeFruit.h" //OrangeFruit.m
@implementation OrangeFruit
@synthesize name;
// 甜
- (void)sweet {
NSLog(@"%@非常甜的啦-----%s",self.name, __func__);
}
// 不好吃
- (void)poorTaste {
NSLog(@"%@不好的啦-----%s",self.name, __func__);
}
/**< 酸橘子 */
- (void)acidOrange {
NSLog(@"%@有點酸-----%s",self.name, __func__);
}
@end
FruitFactory類:
#import <Foundation/Foundation.h> //FruitFactory.h
#import "Fruits.h"
#import "AppleFruit.h"
#import "OrangeFruit.h"
typedef NS_ENUM(NSInteger,FruitType){
FruitTypeApple,
FruitTypeOrange,
};
@interface FruitFactory : NSObject
// 創(chuàng)造水果的工廠
+ (Fruits *)fruitsFactory:(FruitType)type;
@end
#import "FruitFactory.h" //FruitFactory.m
@implementation FruitFactory
+ (Fruits *)fruitsFactory:(FruitType)type {
// 創(chuàng)建空的對象.在工廠方法里面進行水果的制造
Fruits *fruits = nil;
switch (type) {
case FruitTypeApple:
fruits = [[AppleFruit alloc] init];
break;
case FruitTypeOrange:
fruits = [[OrangeFruit alloc] init];
break;
default:
break;
}
return fruits;
}
@end
運行代碼:
#import "ViewController.h"
#import "FruitFactory.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/*###############SimpleFactoryPattern(簡單工廠模式)######################*/
// 在水果工廠里面創(chuàng)建出蘋果
Fruits *fruit = [FruitFactory fruitsFactory:FruitTypeApple];
fruit.name = @"蘋果";
[fruit sweet];
// 在水果工廠里面創(chuàng)建出蘋果
Fruits *fruit1 = [FruitFactory fruitsFactory:FruitTypeOrange];
fruit1.name = @"橘子";
[fruit1 poorTaste];
// 在水果工廠里面創(chuàng)建出蘋果, 調(diào)用私有的方法
AppleFruit *apple = (AppleFruit*)[FruitFactory fruitsFactory:FruitTypeApple];
apple.name = @"蘋果";
[apple freshApple];
// 在水果工廠里面創(chuàng)建出橘子, 調(diào)用私有的方法
OrangeFruit *orage = (OrangeFruit *)[FruitFactory fruitsFactory:FruitTypeOrange];
orage.name = @"橘子";
[orage acidOrange];
}
@end
打印結(jié)果:
2019-12-10 16:07:55.643264+0800 設(shè)計模式[78854:2676436] 蘋果非常甜的啦------[AppleFruit sweet]
2019-12-10 16:07:55.643415+0800 設(shè)計模式[78854:2676436] 橘子不好的啦------[OrangeFruit poorTaste]
2019-12-10 16:07:55.643524+0800 設(shè)計模式[78854:2676436] 蘋果是新鮮的------[AppleFruit freshApple]
2019-12-10 16:07:55.643629+0800 設(shè)計模式[78854:2676436] 橘子有點酸------[OrangeFruit acidOrange]
5蜓斧、總結(jié)
簡單工廠模式的簡化:有時候,為了簡化簡單工廠模式睁冬,我們可以將抽象產(chǎn)品類和工廠類合并挎春,將靜態(tài)工廠方法移至抽象產(chǎn)品類中。比如在Fruits類中添加一個方法:
Fruits類:
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger,FruitType){
FruitTypeApple,
FruitTypeOrange,
};
@interface Fruits : NSObject
/**水果名*/
@property (nonatomic,copy) NSString *name;
- (void)sweet; /**< 甜 */
- (void)poorTaste; /**< 不好吃 */
// 創(chuàng)造水果的工廠
+ (Fruits *)fruitsFactory:(FruitType)type;
@end
#import "Fruits.h"
#import "AppleFruit.h"
#import "OrangeFruit.h"
@implementation Fruits
// 甜
- (void)sweet {}
// 不好吃
- (void)poorTaste {}
+ (Fruits *)fruitsFactory:(FruitType)type {
// 創(chuàng)建空的對象.在工廠方法里面進行水果的制造
Fruits *fruits = nil;
switch (type) {
case FruitTypeApple:
fruits = [[AppleFruit alloc]init];
break;
case FruitTypeOrange:
fruits = [[OrangeFruit alloc]init];
break;
default:
break;
}
return fruits;
}
@end
運行代碼:
Fruits *fruit = [Fruits fruitsFactory:FruitTypeApple];
fruit.name = @"蘋果";
[fruit sweet];
AppleFruit *apple = (AppleFruit*)[Fruits fruitsFactory:FruitTypeApple];
apple.name = @"蘋果";
[apple freshApple];
? 簡單工廠模式提供了專門的工廠類用于創(chuàng)建對象,將對象的創(chuàng)建和對象的使用分離開直奋,它作為一種最簡單的工廠模式在軟件開發(fā)中得到了較為廣泛的應(yīng)用能庆。
1)優(yōu)點
工廠類包含必要的判斷邏輯,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實例脚线,客戶端可以免除直接創(chuàng)建產(chǎn)品對象的職責(zé)搁胆,而僅僅“消費”產(chǎn)品,簡單工廠模式實現(xiàn)了對象創(chuàng)建和使用的分離殉挽。
客戶端無須知道所創(chuàng)建的具體產(chǎn)品類的類名丰涉,只需要知道具體產(chǎn)品類所對應(yīng)的參數(shù)即可,對于一些復(fù)雜的類名斯碌,通過簡單工廠模式可以在一定程度減少使用者的記憶量一死。
通過引入配置文件,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類傻唾,在一定程度上提高了系統(tǒng)的靈活性投慈。
2)缺點
由于工廠類集中了所有產(chǎn)品的創(chuàng)建邏輯,職責(zé)過重冠骄,一旦不能正常工作伪煤,整個系統(tǒng)都要受到影響。
系統(tǒng)擴展困難凛辣,一旦添加新產(chǎn)品就不得不修改工廠邏輯抱既,在產(chǎn)品類型較多時,有可能造成工廠邏輯過于復(fù)雜扁誓,不利于系統(tǒng)的擴展和維護防泵。
簡單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無法形成基于繼承的等級結(jié)構(gòu)蝗敢。
3)適用場景
工廠類負責(zé)創(chuàng)建的對象比較少捷泞,由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務(wù)邏輯太過復(fù)雜寿谴。
客戶端只知道傳入工廠類的參數(shù)锁右,對于如何創(chuàng)建對象并不關(guān)心。
暫時先寫到這讶泰,后續(xù)有時間再更新...