读《大话设计模式》一

2018-12-11  本文已影响10人  LeverTsui

前言

对设计模式的理解,不够透彻,有时去找资料,总是零零散散,不成系统,故将《大话设计模式》中的干货整理下,方便需要使用时可以参考使用。

设计模式六大原则

单一职责原则

里氏替换原则

依赖倒转原则

接口隔离原则

迪米特法则

开放-封闭原则

六大原则总结

用抽象构建框架,用实现扩展细节。

设计模式六大原则

UML基础知识

UML类图图示

类与类之间的关系

各种关系的强弱顺序:
泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖

常用的23中设计模式

创建型模式

简单工厂模式

模式动机

考虑一个简单的软件应用场景,一个计算器有不同的按钮(如+、-、*、÷), 这些按钮都源自同一个基类,不过在继承基类后不同的子类修改了部分属性从而使得它们可以完成不同的功能,如果我们希望在使用这些按钮时,不需要知道这些具体按钮类的名字,只需要知道表示该按钮类的一个参数,并提供一个调用方便的方法,把该参数传入方法即可返回一个相应的按钮对象,此时,就可以使用简单工厂模式。

模式定义

简单工厂模式(Simple Factory Pattern):它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式结构

简单工厂模式包含如下角色:

简单工厂模式类图
时序图
简单工厂模式时序图
源码
//HCDCalculateProtocol.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, HCDCalculateType) {
    HCDCalculateTypeAdd = 0,   //加
    HCDCalculateTypeMinus,     //减
    HCDCalculateTypeMultipy,   //乘
    HCDCalculateTypeDivide     //除
};

@protocol HCDCalculateProtocol <NSObject>

@optional
-(CGFloat)calculate;

@end
//HCDCalculate.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "HCDCalculateProtocol.h"

@interface HCDCalculate : NSObject <HCDCalculateProtocol>

@property(nonatomic, assign) CGFloat numberA;
@property(nonatomic, assign) CGFloat numberB;

@end
//HCDCalcuteFactory.h
#import <Foundation/Foundation.h>
#import "HCDCalculate.h"

@interface HCDCalcuteFactory : NSObject

+(HCDCalculate *)createCalcute:(NSString *)calculatetype;

@end

//HCDCalcuteFactory.m
#import "HCDCalcuteFactory.h"
#import "HCDCalculateAdd.h"
#import "HCDCalculateDivide.h"
#import "HCDCalculateMinus.h"
#import "HCDCalcuteMultiply.h"

@implementation HCDCalcuteFactory

+(HCDCalculate *)createCalcute:(NSString *)calculatetype {
    
    NSArray *calculateArray = @[@"+",@"-",@"*",@"/"];
    
    if (![calculateArray containsObject:calculatetype]) {
        return nil;
    }
    HCDCalculateType calType = [calculateArray indexOfObject:calculatetype];
    
    
    switch (calType) {
        case HCDCalculateTypeAdd:
            return [[HCDCalculateAdd alloc]init];
            break;
        case HCDCalculateTypeMinus:
            return [[HCDCalculateMinus alloc]init];
            break;
        case HCDCalculateTypeMultipy:
            return [[HCDCalcuteMultiply alloc]init];
        case HCDCalculateTypeDivide:
            return [[HCDCalculateDivide alloc]init];
    }
}
@end
//HCDCalculateAdd.m
#import "HCDCalculateAdd.h"

@implementation HCDCalculateAdd

-(CGFloat)calculate{
    return self.numberA + self.numberB;
}
@end

//HCDCalculateMinus.m
#import "HCDCalculateMinus.h"

@implementation HCDCalculateMinus

-(CGFloat)calculate{
    return self.numberA - self.numberB;
}

@end

//HCDCalcuteMultiply
#import "HCDCalcuteMultiply.h"

@implementation HCDCalcuteMultiply

-(CGFloat)calculate{
    return self.numberA * self.numberB;
}
@end

//HCDCalculateDivide.m
#import "HCDCalculateDivide.h"

@implementation HCDCalculateDivide

- (CGFloat)calculate{
    if (self.numberB == 0) {
        NSLog(@"dividend is can not be zero!");
        return 0;
    }
    return self.numberA/self.numberB;
}

@end

工厂方法模式

模式动机

现在对该系统进行修改,不再设计一个运算工厂类来统一负责所有产品的创建,而是将具体运算的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的运算工厂类,再定义具体的工厂类来生成加法运算、减法运算、乘法运算等,它们实现在抽象按钮工厂类中定义的方法。这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新运算的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“开闭原则”。

模式定义

工厂方法模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

模式结构

工厂方法模式包含如下角色:

时序图
工厂方法模式时序图
源码
//HCDfactory.h

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

@interface HCDfactory : NSObject

-(HCDCalculate *)createFactory;

@end

//HCDfactory.m
#import "HCDfactory.h"

@implementation HCDfactory

-(HCDCalculate *)createFactory {
    return nil;
}

@end

//HCDfactoryAdd.m
@implementation HCDfactoryAdd

-(HCDCalculate *)createFactory {
    return [[HCDCalculateAdd alloc]init];
}
@end

//HCDfactoryMinus.m
@implementation HCDfactoryMinus

-(HCDCalculate *)createFactory {
    return [[HCDCalculateMinus alloc]init];
}
@end

//HCDfactoryMultiply.m
@implementation HCDfactoryMultiply

-(HCDCalculate *)createFactory {
    return [[HCDCalcuteMultiply alloc]init];
}
@end

//HCDfactoryDivide.m
@implementation HCDfactoryDivide

-(HCDCalculate *)createFactory {
    return [[HCDCalculateDivide alloc]init];
}
@end
//HCDCalculate.h
@interface HCDCalculate : NSObject <HCDCalculateProtocol>

@property(nonatomic, assign) CGFloat numberA;
@property(nonatomic, assign) CGFloat numberB;

@end

//HCDCalculateAdd.m
@implementation HCDCalculateAdd

-(CGFloat)calculate{
    return self.numberA + self.numberB;
}
@end

//HCDCalculateMinus.m
@implementation HCDCalculateMinus

-(CGFloat)calculate{
    return self.numberA - self.numberB;
}

@end

//HCDCalcuteMultiply.m
@implementation HCDCalcuteMultiply

-(CGFloat)calculate{
    return self.numberA * self.numberB;
}
@end

//HCDCalculateDivide.m
@implementation HCDCalculateDivide

- (CGFloat)calculate{
    if (self.numberB == 0) {
        NSLog(@"dividend is can not be zero!");
        return 0;
    }
    return self.numberA/self.numberB;
}

@end

//HCDCalculateProtocol.h
typedef NS_ENUM(NSInteger, HCDCalculateType) {
    HCDCalculateTypeAdd = 0,   //加
    HCDCalculateTypeMinus,     //减
    HCDCalculateTypeMultipy,   //乘
    HCDCalculateTypeDivide     //除
};

@protocol HCDCalculateProtocol <NSObject>

@optional
-(CGFloat)calculate;

@end
//使用示例
    HCDfactory *addFactory = [[HCDfactoryAdd alloc]init];
    HCDCalculate *addCalculate = [addFactory createFactory];
    addCalculate.numberA = 10;
    addCalculate.numberB = 15;
    NSLog(@"结果是%f\n",[addCalculate calculate]);
    
    HCDfactory *minusFactory = [[HCDfactoryMinus alloc]init];
    HCDCalculate *minusCalculate = [minusFactory createFactory];
    minusCalculate.numberA = 10;
    minusCalculate.numberB = 15;
    NSLog(@"结果是%f\n",[minusCalculate calculate]);
    
    HCDfactory *multiplyFactory = [[HCDfactoryMultiply alloc]init];
    HCDCalculate *multiplyCalculate = [multiplyFactory createFactory];
    multiplyCalculate.numberA = 10;
    multiplyCalculate.numberB = 15;
    NSLog(@"结果是%f\n",[multiplyCalculate calculate]);
    
    HCDfactory *divideFactory = [[HCDfactoryDivide alloc]init];
    HCDCalculate *divideCalculate = [divideFactory createFactory];
    divideCalculate.numberA = 10;
    divideCalculate.numberB = 15;
    NSLog(@"结果是%f\n",[divideCalculate calculate]);
    

抽象工厂模式

模式动机
模式定义

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。属于对象创建型模式。

模式结构

抽象工厂模式包含如下角色:

抽象工厂模式类图
时序图
抽象工厂模式时序图
源码
//HCDFactory.h
@protocol HCDFactory <NSObject>

-(id<HCDUser>)createUser;
-(id<HCDDepartment>)createDepartment;

@end

//HCDSqlserverFactory.m
@implementation HCDSqlserverFactory

-(id<HCDUser>)createUser{
    return [[HCDSqlserverUser alloc]init];
}

-(id<HCDDepartment>)createDepartment{
    return [[HCDSqlserverDepartment alloc]init];
}

@end

//HCDAccessFactory.m
-(id<HCDUser>)createUser{
    return [[HCDAccessUser alloc]init];
}

-(id<HCDDepartment>)createDepartment{
    return [[HCDAccessDepartment alloc]init];
}

@end 
//HCDDepartment.h
@protocol HCDDepartment <NSObject>

-(void)insertDepartment:(SQLDepartment *)department;

-(SQLDepartment *)getDepartment;

@end

//HCDSqlserverDepartment.m
@implementation HCDSqlserverDepartment

-(SQLDepartment *)getDepartment{
    NSLog(@"新建一个Sqlserver的SQLDepartment对象");
    return [[SQLDepartment alloc]init];
}

-(void)insertDepartment:(SQLDepartment *)department{
    NSLog(@"插入一个Sqlserver的SQLDepartment对象");
}

@end

//HCDAccessDepartment.m
@implementation HCDAccessDepartment

-(SQLDepartment *)getDepartment{
    NSLog(@"新建一个Access的SQLDepartment对象");
    return [[SQLDepartment alloc]init];
}

-(void)insertDepartment:(SQLDepartment *)department{
    NSLog(@"插入一个Access的SQLDepartment对象");
}

@end
//HCDUser.h
@protocol HCDUser <NSObject>

-(void)insertUser:(SQLUser *)user;

-(SQLUser *)getUser;

@end

//HCDSqlserverUser.m
@implementation HCDSqlserverUser

-(SQLUser *)getUser{
    NSLog(@"新建一个Sqlserver的SQLUser对象");
    return [[SQLUser alloc]init];
}

-(void)insertUser:(SQLUser *)user{
     NSLog(@"插入一个Sqlserver的SQLUser对象");
}

@end

//HCDAccessUser.m
@implementation HCDAccessUser

-(SQLUser *)getUser{
    NSLog(@"新建一个Access的SQLUser对象");
    return [[SQLUser alloc]init];
}

-(void)insertUser:(SQLUser *)user{
    NSLog(@"插入一个Access的SQLUser对象");
}

@end
//使用示例
    id<HCDFactory> factory0 = [[HCDSqlserverFactory alloc]init];
    id<HCDDepartment> department0 = [factory0 createDepartment];
    [department0 insertDepartment:[[SQLDepartment alloc]init]];
    [department0 getDepartment];
    
    id<HCDUser> user0 = [factory0 createUser];
    [user0 insertUser:[[SQLUser alloc] init]];
    [user0 getUser];
    
    id<HCDFactory> factory1 = [[HCDAccessFactory alloc]init];
    id<HCDDepartment> department1 = [factory1 createDepartment];
    [department1 insertDepartment:[[SQLDepartment alloc]init]];
    [department1 getDepartment];
    
    id<HCDUser> user1 = [factory1 createUser];
    [user1 insertUser:[[SQLUser alloc] init]];
    [user1 getUser];

建造者模式

模式动机

无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发送机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。

模式定义

造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

模式结构

建造者模式包含如下角色:

时序图
建造者模式时序图
源码
//HCDPersonBuilderDirector.h
@class HCDPresionBuilder;
@interface HCDPersonBuilderDirector : NSObject

- (instancetype)initWithBuilder:(HCDPresionBuilder *)builder;

- (void)buildPerson; 

@end

//HCDPersonBuilderDirector.m
@interface HCDPersonBuilderDirector ()

@property (nonatomic, strong) HCDPresionBuilder *builder;

@end

@implementation HCDPersonBuilderDirector

- (instancetype)initWithBuilder:(HCDPresionBuilder *)builder {
    self = [super init];
    if (self) {
        self.builder = builder;
    }
    return self;
}

- (void)buildPerson {
    [self.builder buildHead];
    [self.builder buildBody];
    [self.builder buildArmLeft];
    [self.builder buildArmRight];
    [self.builder buildLegLeft];
    [self.builder buildLegRight];
    [self.builder getResult];
}

@end
//HCDPresionBuilderProtocol.h
ypedef  NS_ENUM(NSUInteger,HCDBuildOption){
    HCDBuildOptionFat = 0,  //胖的人
    HCDBuildOptionThin      //瘦的人
};

@protocol HCDPresionBuilderProtocol <NSObject>

- (void)buildHead;
- (void)buildBody;
- (void)buildArmLeft;
- (void)buildArmRight;
- (void)buildLegLeft;
- (void)buildLegRight;

- (HCDProduct *)getResult;

@end 

//HCDPresionBuilder.h
@interface HCDPresionBuilder : NSObject<HCDPresionBuilderProtocol>

@end

//HCDPersonFatBuilder.m
@interface HCDPersonFatBuilder()

@property (nonatomic, strong) HCDProduct *product;

@end

@implementation HCDPersonFatBuilder

-(instancetype)init{
    self = [super init];
    if (self) {
        _product = [[HCDProduct alloc] init];
    }
    return self;
} 

- (void)buildHead {
    NSLog(@"建造胖子的头部");
    [self.product.header work];
}

- (void)buildBody {
    NSLog(@"建造胖子的身体");
    [self.product.body work];
}

- (void)buildArmLeft {
    NSLog(@"建造胖子的左手");
    [self.product.arm work];
}

- (void)buildArmRight {
    NSLog(@"建造胖子的右手");
    [self.product.arm work];
}

- (void)buildLegLeft {
    NSLog(@"建造胖子的左脚");
    [self.product.leg work];
}

- (void)buildLegRight {
    NSLog(@"建造胖子的右脚");
    [self.product.leg work];
}

- (HCDProduct *)getResult {
    return self.product;
}

@end

//HCDPersonThinBuilder.m
@interface HCDPersonThinBuilder ()

@property (nonatomic, strong) HCDProduct *product;

@end

@implementation HCDPersonThinBuilder

-(instancetype)init{
    self = [super init];
    if (self) {
        _product = [[HCDProduct alloc] init];
    }
    return self;
}
 
- (void)buildHead {
    NSLog(@"建造瘦子的头部");
    [self.product.header work];
}

- (void)buildBody {
    NSLog(@"建造瘦子的身体");
    [self.product.body work];
}

- (void)buildArmLeft {
    NSLog(@"建造瘦子的左手");
    [self.product.arm work];
}

- (void)buildArmRight {
    NSLog(@"建造瘦子的右手");
    [self.product.arm work];
}

- (void)buildLegLeft {
    NSLog(@"建造瘦子的左脚");
    [self.product.leg work];
}

- (void)buildLegRight {
    NSLog(@"建造瘦子的右脚");
    [self.product.leg work];
}

- (HCDProduct *)getResult {
    return self.product;
}

@end
//使用示例
- (IBAction)buildFat:(id)sender {
    HCDPersonFatBuilder *builder = [[HCDPersonFatBuilder alloc]init];
    HCDPersonBuilderDirector *director = [[HCDPersonBuilderDirector alloc] initWithBuilder:builder];
    [director buildPerson];
}

- (IBAction)buildThin:(id)sender {
    HCDPersonThinBuilder *builder = [[HCDPersonThinBuilder alloc]init];
    HCDPersonBuilderDirector *director = [[HCDPersonBuilderDirector alloc] initWithBuilder:builder];
    [director buildPerson];
}

单例模式

模式动机

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。
一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机

模式定义

单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

模式结构
单例模式类图
时序图
单例模式时序图
源码
+(instancetype)sharedInstance{
    static HCDSingleton *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[HCDSingleton alloc]init];
    });
    return singleton;
}

原型模式

模式动机
模式定义

使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
备注:复制分浅复制和深复制

iOS深拷贝和浅拷贝

结构式模式

组合模式

模式动机
模式定义

将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

模式结构

模板方法模式包含如下角色:

时序图

源码
    //使用示例
    HCDConcreteCompany *root = [[HCDConcreteCompany alloc] initWithName:@"总公司"];
    [root add:[[HCDHRDepartment alloc] initWithName:@"总公司人力资源部"]];
    [root add:[[HCDFinanceDepartment alloc] initWithName:@"总公司财务部"]];
    
    HCDConcreteCompany *comp = [[HCDConcreteCompany alloc] initWithName:@"上海华东分公司"];
    [comp add:[[HCDHRDepartment alloc] initWithName:@"上海华东分公司人力资源部"]];
    [comp add:[[HCDFinanceDepartment alloc] initWithName:@"上海华东分公司财务部"]];
    [root add:comp];
    
    HCDConcreteCompany *office = [[HCDConcreteCompany alloc] initWithName:@"杭州办事处"];
    [office add:[[HCDHRDepartment alloc] initWithName:@"杭州办事处人力资源部"]];
    [office add:[[HCDFinanceDepartment alloc] initWithName:@"杭州办事处财务部"]];
    NSLog(@"\n");
    [comp add:office];
    NSLog(@"结构图:--------------------------");
    [root display:1];
    NSLog(@"\n");
    NSLog(@"职责:---------------------------");
    [root lineofDuty];
//HCDCompany.h
@interface HCDCompany : NSObject

@property (nonatomic,copy) NSString *name;

- (instancetype)initWithName:(NSString *)name;

-(void)add:(HCDCompany *)company;

-(void)remove:(HCDCompany *)company;

-(void)display:(NSInteger)depth;

-(void)lineofDuty;

@end
//HCDConcreteCompany.h
@interface HCDConcreteCompany : HCDCompany

@end

//HCDConcreteCompany.m
@interface HCDConcreteCompany ()

@property (nonatomic, strong) NSMutableArray *childList;

@end

@implementation HCDConcreteCompany

- (instancetype)initWithName:(NSString *)name{
    self = [super initWithName:name];
    if (self) { 
        _childList = [NSMutableArray array];
    }
    return self;
}

- (void)add:(HCDCompany *)company{
    [self.childList addObject:company];
}

- (void)remove:(HCDCompany *)company{
    [self.childList removeObject:company];
}

- (void)display:(NSInteger)depth {
    NSString *seperate = @"";
    for (NSInteger i = 0; i < depth; i++) {
        seperate = [seperate stringByAppendingString:@"-"];
    }
    NSLog(@"%@%@的子公司",seperate,self.name);
    for (HCDCompany * company in self.childList) {
        [company display:depth + 2];
    }
}

- (void)lineofDuty{
    NSLog(@"%@的子公司的职责",self.name);
    for (HCDCompany * company in self.childList) {
        [company lineofDuty];
    }
}

@end
//HCDHRDepartment.h
@interface HCDHRDepartment : HCDCompany 

@end

//HCDHRDepartment.m
@implementation HCDHRDepartment

-(void)add:(HCDCompany *)company{
    
}

- (void)display:(NSInteger)depth {
    NSString *seperate = @"";
    for (NSInteger i = 0; i < depth; i++) {
        seperate = [seperate stringByAppendingString:@"-"];
    }
    NSLog(@"%@%@的HR部门",seperate,self.name);
}

-(void)remove:(HCDCompany *)company{

}

-(void)lineofDuty{
    NSLog(@"%@,培训员工",self.name);
}

@end
//HCDFinanceDepartment.h
@interface HCDFinanceDepartment : HCDCompany

@end

//HCDFinanceDepartment.m
@implementation HCDFinanceDepartment

-(void)add:(HCDCompany *)company{
    
}

-(void)remove:(HCDCompany *)company{
    
}

- (void)display:(NSInteger)depth {
    NSString *seperate = @"";
    for (NSInteger i = 0; i < depth; i++) {
        seperate = [seperate stringByAppendingString:@"-"];
    }
    NSLog(@"%@%@的财务部门",seperate,self.name);
}

-(void)lineofDuty{
    NSLog(@"%@,给员工发钱",self.name);
}

@end
上一篇 下一篇

猜你喜欢

热点阅读