设计模式1-工厂方法模式、抽象工厂模式

引言

世上本没有路,走的人多了便成了路。软件本没有什么设计模式,一个问题的解决方案使用的人和次数多了便成为了某一种设计模式..... (个人觉得,😄)

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

设计模式的分类

总体来说设计模式分为三大类:

  • 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

  • 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

  • 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

设计模式的六大原则

1、开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

5、迪米特法则(最少知道原则)(Demeter Principle)

为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承。

对于同一种模式,每个人的理解都不同,能解决实际问题才是关键

工厂方法模式

工厂方法模式,顾名思义工厂嘛是生产产品的,生产产品那种方式最快呢?当人是流水线作业嘛,那么怎样才能流水线生产产品呢,这些产品必须要具有相同的生产工艺和生产流程。所以工厂模式就是:工厂模式就是定义创建对象的接口(工厂),让子类决定实例化哪一个类(这些类具有一套相同接口,但是实例化的方式略有差异,即:这些接口的具体实现不同)。这样,类的实例化就推迟到了子类工厂方法模式又有简单工厂模式(工厂模式的简化版),工厂方法模式,多工厂方法模式(工厂模式的扩展)。下面我们来看看多工厂方法模式:

多工厂方法模式UML图

例子(oc版):


//创建产品的公共操作协议
@protocol DPFactoryProtocol <NSObject>

@optional

- (DPFactoryProductBaseClass *)factoryCreateProduct;

@end

//创建基类并遵守协议
@interface DPFactoryBaseClass : NSObject <DPFactoryProtocol>

@end

// 创建产品A类,可以遵守产品协议,也可以继承产品基类 需要实现产品协议中的方法
@interface DPFactoryA : NSObject <DPFactoryProtocol>

@end
#import "DPFactoryA.h"
#import "DPFactoryProductA.h"


@implementation DPFactoryA

- (DPFactoryProductBaseClass *)factoryCreateProduct{
    DPFactoryProductA * product = [[DPFactoryProductA alloc] init];
    return product;
}


@end

#import <Foundation/Foundation.h>
#import "DPFactoryProtocol.h"

// 创建产品B类,可以遵守产品协议,也可以继承产品基类 需要实现产品协议中的方法
@interface DPFactoryB : NSObject<DPFactoryProtocol>

@end
#import "DPFactoryB.h"
#import "DPFactoryProductB.h"


@implementation DPFactoryB

- (DPFactoryProductBaseClass *)factoryCreateProduct{
    DPFactoryProductB * product = [[DPFactoryProductB alloc] init];
    return product;
}


@end

#import <Foundation/Foundation.h>

//创建工厂协议
@protocol DPFactoryProductProtocol <NSObject>

@optional

- (void)productFunction;

@end

//创建工厂基类
@interface DPFactoryProductBaseClass : NSObject <DPFactoryProductProtocol>

@end

#import <Foundation/Foundation.h>
#import "DPFactoryProductProtocol.h"

//创建生产产品A的工厂, 它必须继承工厂协议或者继承工厂基类
@interface DPFactoryProductA : DPFactoryProductBaseClass

@end
#import "DPFactoryProductA.h"

@implementation DPFactoryProductA

- (void)productFunction{
    NSLog(@"我是工厂模式生产出来的A产品");
}

@end

#import <Foundation/Foundation.h>
#import "DPFactoryProductProtocol.h"

//创建生产产品B的工厂, 它必须继承工厂协议或者继承工厂基类
@interface DPFactoryProductB :DPFactoryProductBaseClass

@end
#import "DPFactoryProductB.h"

@implementation DPFactoryProductB

- (void)productFunction{
    NSLog(@"我是工厂模式生产出来的B产品");
}

@end


typedef NS_ENUM(NSInteger, ProductType) {

    ProductTypeA,
    ProductTypeB
};

//供客户使用的类
@interface DPFactoryUseForClent : NSObject

//根据客户传入的产品类型生产出相应的产品
- (DPFactoryProductBaseClass *)createProductWithProductType:(ProductType) productType;

@end
@implementation DPFactoryUseForClent

- (DPFactoryProductBaseClass *)createProductWithProductType:(ProductType) productType{
    
    DPFactoryProductBaseClass * product = nil;
    switch (productType) {
        case ProductTypeA:
        {
            DPFactoryA * factory = [[DPFactoryA alloc] init];
            product = [factory factoryCreateProduct];
        }
            break;
        case ProductTypeB:
        {
            DPFactoryB * factory = [[DPFactoryB alloc] init];
            product = [factory factoryCreateProduct];
        }
            break;
        default:
            break;
    }
    
    return product;
}

@end

 //客户端使用
    DPFactoryUseForClent * clent = [[DPFactoryUseForClent alloc]init];
    DPFactoryProductBaseClass * productA = [clent createProductWithProductType:ProductTypeA];
    [productA productFunction];
    
    DPFactoryProductBaseClass * productB = [clent createProductWithProductType:ProductTypeB];
    [productB productFunction];


2017-01-04 14:43:00.303 DesignPatterns[40735:3389989] 我是工厂模式生产出来的A产品
2017-01-04 14:43:00.304 DesignPatterns[40735:3389989] 我是工厂模式生产出来的B产品



抽象工厂模式

抽象工厂模式顾名思义是对工厂模式中工厂的进一步抽象,但他又不同于多工厂工厂模式,它提供一个创建一系列的相互依赖的接口,而无需指定他们具体的类。一般抽象工厂都是生成一组相互依赖的产品的,往往是多个。下面我们来看看抽象工厂模式:

抽象工厂模式UML图

例子(oc版):


@protocol DPCreateNotebookComputerProtocol <NSObject>

@optional
- (void)createNotebookComputer;

@end

@interface DPCreateNotebookComputerBaseClass : NSObject<DPCreateNotebookComputerProtocol>

@end

#import <Foundation/Foundation.h>
#import "DPCreateNotebookComputerProtocol.h"


@interface DPCreateHuaWeiNotebookComputer : DPCreateNotebookComputerBaseClass

@end
#import "DPCreateHuaWeiNotebookComputer.h"

@implementation DPCreateHuaWeiNotebookComputer

- (void)createNotebookComputer{
    NSLog(@"我是抽象工厂模式生产的华为笔记本电脑");
}

@end


#import <Foundation/Foundation.h>
#import "DPCreateNotebookComputerProtocol.h"


@interface DPIphoneNotebookComputer : DPCreateNotebookComputerBaseClass

@end
#import "DPIphoneNotebookComputer.h"

@implementation DPIphoneNotebookComputer

- (void)createNotebookComputer{
    NSLog(@"我是抽象工厂模式生产的苹果笔记本电脑");
}

@end


#import <Foundation/Foundation.h>


@protocol DPCreatePhoneProtocol <NSObject>

@optional

- (void)createPhone;

@end

@interface DPCreatePhoneBase : NSObject<DPCreatePhoneProtocol>

@end


#import <Foundation/Foundation.h>
#import "DPCreatePhoneProtocol.h"


@interface DPCreateHuaWeiPhone :DPCreatePhoneBase

@end
#import "DPCreateHuaWeiPhone.h"

@implementation DPCreateHuaWeiPhone


- (void)createPhone{
    NSLog(@"我是抽象工厂模式生产的华为手机");
}


@end


#import <Foundation/Foundation.h>
#import "DPCreatePhoneProtocol.h"

@interface DPCreateiPhone6s : DPCreatePhoneBase

@end
#import "DPCreateiPhone6s.h"

@implementation DPCreateiPhone6s

- (void)createPhone{
    NSLog(@"我是抽象工厂模式生产的苹果6s手机");
}

@end


#import <Foundation/Foundation.h>
#import "DPCreateNotebookComputerProtocol.h"
#import "DPCreatePhoneProtocol.h"


@protocol DPAbstractFactoryProtocol <NSObject>

@optional
- (DPCreateNotebookComputerBaseClass *)factoryCreateNotebookComputer;
- (DPCreatePhoneBase *)factoryCreatePhone;

@end

@interface DPFactoryBase : NSObject<DPAbstractFactoryProtocol>

@end


#import <Foundation/Foundation.h>
#import "DPFactoryProtocol.h"


@interface DPHuaWeiFactory : DPFactoryBase

@end
#import "DPHuaWeiFactory.h"
#import "DPCreateHuaWeiNotebookComputer.h"
#import "DPCreateHuaWeiPhone.h"



@implementation DPHuaWeiFactory

- (id<DPCreateNotebookComputerProtocol>)factoryCreateNotebookComputer{

    DPCreateHuaWeiNotebookComputer * computer = [[DPCreateHuaWeiNotebookComputer alloc] init];
    return computer;
}

- (id<DPCreatePhoneProtocol>)factoryCreatePhone{

    DPCreateHuaWeiPhone * phone = [[DPCreateHuaWeiPhone alloc] init];
    return phone;
}
@end


#import <Foundation/Foundation.h>
#import "DPFactoryProtocol.h"


@interface DPIPhoneFactory : DPFactoryBase

@end
#import "DPIPhoneFactory.h"
#import "DPIphoneNotebookComputer.h"
#import "DPCreateiPhone6s.h"



@implementation DPIPhoneFactory
- (id<DPCreateNotebookComputerProtocol>)factoryCreateNotebookComputer{
    
    DPIphoneNotebookComputer * computer = [[DPIphoneNotebookComputer alloc] init];
    return computer;
}

- (id<DPCreatePhoneProtocol>)factoryCreatePhone{
    
    DPCreateiPhone6s * phone = [[DPCreateiPhone6s alloc] init];
    return phone;
}
@end

#import <Foundation/Foundation.h>
#import "DPIphoneNotebookComputer.h"
#import "DPCreateiPhone6s.h"
#import "DPCreateHuaWeiNotebookComputer.h"
#import "DPCreateHuaWeiPhone.h"
#import "DPFactoryProtocol.h"
#import "DPIPhoneFactory.h"
#import "DPHuaWeiFactory.h"

typedef NS_ENUM(NSInteger, FactoryType) {
    HuaWei,
    iPhone

};

@interface DPAbstractFactoryUseForClent : NSObject

- (DPFactoryBase *)clentCreateFactoryWith:(FactoryType) FactoryType;


@end
#import "DPAbstractFactoryUseForClent.h"




@implementation DPAbstractFactoryUseForClent

- (DPFactoryBase *)clentCreateFactoryWith:(FactoryType) FactoryType{
    
    DPFactoryBase * factory = nil;
    switch (FactoryType) {
        case HuaWei:
        {
            factory = [[DPHuaWeiFactory alloc] init];
        }
            break;
        case iPhone:
        {
            factory = [[DPIPhoneFactory alloc] init];
        }
            break;    
        default:
            break;
    }
    
    return factory;
    
}

@end


//客户端使用
DPAbstractFactoryUseForClent * clent = [[DPAbstractFactoryUseForClent alloc] init];
        
        DPFactoryBase * factoryHuaWei = [clent clentCreateFactoryWith:HuaWei];
        
        DPCreateNotebookComputerBaseClass * huaWeiNoteBook = [factoryHuaWei factoryCreateNotebookComputer];
        [huaWeiNoteBook createNotebookComputer];
        
        DPCreatePhoneBase * huaWeiPhone = [factoryHuaWei factoryCreatePhone];
        [huaWeiPhone createPhone];
        
        DPFactoryBase * factoryiPhone = [clent clentCreateFactoryWith:iPhone];
        
        DPCreateNotebookComputerBaseClass * iPhoneNoteBook = [factoryiPhone factoryCreateNotebookComputer];
        [iPhoneNoteBook createNotebookComputer];
        
        DPCreatePhoneBase * iPhone = [factoryiPhone factoryCreatePhone];
        [iPhone createPhone];
        
        
        
        2017-01-04 16:37:51.545 DesignPatterns[41125:3455076] 我是抽象工厂模式生产的华为笔记本电脑
2017-01-04 16:37:51.546 DesignPatterns[41125:3455076] 我是抽象工厂模式生产的华为手机
2017-01-04 16:37:51.546 DesignPatterns[41125:3455076] 我是抽象工厂模式生产的苹果笔记本电脑
2017-01-04 16:37:51.546 DesignPatterns[41125:3455076] 我是抽象工厂模式生产的苹果6s手机

工厂模式和抽象工厂模式的比较
类族

类簇和工厂模式很类似,它通过在基类中提供工厂方法,隐藏具体的子类实现。例如Cocoa中的类方法

NSNumber * a = [NSNumber numberWithBool:YES];
    NSNumber * b = [NSNumber numberWithInteger:123];
    NSLog(@"%@",NSStringFromClass([a class])); //__NSCFBoolean
    NSLog(@"%@",NSStringFromClass([b class])); //__NSCFNumber

可以看到实际上NSNumber的Runtime类并不是NSNumber,NSNumber只是定义了一个高度抽象的基类,它既是产品类,又是工厂类。通过提供numberWith***一些列方法,隐藏了具体的子类实现。类似的还有[UIButton buttonWithType:].Cocoa中,使用类簇的设计模式有NSDictionary,NSData,NSString等。

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

推荐阅读更多精彩内容

  • 一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者...
    RamboLI阅读 744评论 0 1
  • 原文链接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤独杂货铺阅读 1,508评论 0 3
  • 面向对象设计的五大原则 单一职责原则(SRP) 一个类应该仅有一个职责。 开放封闭原则(OCP) 对扩展开放,...
    LiuHDme阅读 1,453评论 0 3
  • 本文集网络上文章及自己coding和理解的结果而来,是设计模式学习的开篇。 本文介绍设计模式的一些概念,分类,和设...
    月落蝶殇阅读 494评论 0 0
  • 一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者...
    lichengjin阅读 887评论 0 8