iOS--工厂设计模式
设计模式的概念和意义
设计模式(Design Patterns)是一套被反复使用、代码设计经验的总结,一般与编程语言无关,是一套比较成熟的编程思想。它主要解决的是在软件设计中反复出现的问题,并提供了一种解决方案。这些方案是在长期软件开发实践中逐步形成的,旨在提高代码的可重用性、可维护性和可扩展性。
在iOS开发中,设计模式通常与面向对象编程(OOP)的概念相结合,通过类和对象来描述问题域中的事物及其关系。设计模式将最佳实践封装成可复用的代码片段,使开发者能够更快速、更高效地构建高质量的应用程序。
设计模式的意义
-
代码重用性:设计模式提供了一种标准化的方式来组织代码,使得相同的解决方案可以在不同的项目中被重用。这减少了开发人员的工作量,提高了代码的质量。
-
提高代码可读性:设计模式遵循一定的命名和结构规范,使得代码更加清晰易懂。其他开发者可以更容易地理解代码的目的和功能,从而加快项目的开发进度。
-
保证代码可靠性:设计模式经过长期实践的检验,已经被证明是有效的解决方案。使用设计模式可以降低代码出错的可能性,提高应用程序的稳定性。
-
降低维护成本:设计模式使得代码结构更加清晰,易于维护和扩展。当需要修改或添加新功能时,开发人员可以更容易地找到相关的代码并进行修改。
-
促进团队协作:设计模式为开发人员提供了一种共同的语言和框架,使得团队成员之间可以更容易地交流和协作。这有助于提高项目的整体质量和效率。
类族模式
在之前的学习中,我们了解到了类族模式;这里的工厂设计模式和类族模式很像 ;
UIButton作为类族模式的例子
-
抽象基类:UIButton是抽象基类,它定义了按钮的基本属性和行为。开发者通常不会直接创建UIButton的实例,而是通过调用其类方法来创建特定类型的按钮实例。
-
具体子类:虽然开发者无法直接访问或看到UIButton的具体子类,但系统框架中确实存在多个私有子类来实现不同类型的按钮。这些子类根据按钮的类型(如系统按钮、自定义按钮等)和样式(如普通按钮、高亮按钮、禁用按钮等)进行不同的绘制和行为处理。
-
创建按钮实例:
开发者通过调用UIButton的类方法(如buttonWithType:)来创建按钮实例。该方法根据传入的类型参数(如UIButtonTypeSystem、UIButtonTypeRoundedRect等)返回不同子类的实例。
-
在下面的代码中,我们调用buttonWithType:方法并传入UIButtonTypeSystem作为参数来创建一个系统类型的按钮。然后,我们设置按钮的标题、添加点击事件的处理方法,并将其添加到视图中。
objectivec
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"Click Me" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
- 隐藏实现细节
作为开发者,我们无需关心UIButton背后具体是由哪个子类实现的。我们只需要使用UIButton提供的公共接口来设置按钮的属性、添加事件处理方法等。系统框架会根据我们的需求自动选择并创建合适的子类实例。
总结
通过类族模式,UIButton能够隐藏其背后的实现细节,提供统一的公共接口供开发者使用。这简化了开发过程,提高了代码的可读性和可维护性。同时,由于系统框架内部可以根据需要动态选择并创建不同的子类实例,因此也提高了代码的灵活性和可扩展性。
三种工厂设计模式
工厂设计模式主要分为以下三种,每种模式都有其特定的应用场景和优缺点:
简单工厂模式(Simple Factory Pattern):
- 又称为静态工厂方法模式(Static Factory Method Pattern)。
- 通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。不过其实可以使用协议;
- 特点:代码简单,虽有多处if分支且违背开闭原则(对扩展开放,对修改关闭),但扩展性和可读性尚可,这样的代码在大多数情况下并无问题。
代码实例
上面创建了一个专门的工厂类来创建产品类,来实现隐藏产品类的创建实现,其产品类都遵循operation协议并展示接口,但最终只有工厂类的类方法暴露在外被人调用 ;
工厂方法模式(Factory Method Pattern):
- 定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。
- 核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。
- 特点:通过不同的工厂创建不同的对象,每个对象都有自己的工厂来创建。当对象的创建过程比较复杂,需要组合其他类对象做各种初始化操作时,推荐使用工厂方法模式。
代码实例
创建一个抽象类ShapeFactory作为核心工厂类,该类遵循CreateFactory协议中声明的接口 ;
objectivec
#import <Foundation/Foundation.h>
#import "CreateFactory.h"
NS_ASSUME_NONNULL_BEGIN
@interface ShapeFactory : NSObject <CreateFactory>
@end
NS_ASSUME_NONNULL_END
由该抽象工厂类调用接口创建具体的产品工厂类 ;再由具体的产品工厂类创建产品对象 ;
objectivec
#import "ShapeFactory.h"
NS_ASSUME_NONNULL_BEGIN
@interface Factory01 : ShapeFactory
- (id <Shape>)createProduct ;
@end
NS_ASSUME_NONNULL_END
objectivec
#import "Factory01.h"
#import "Product01.h"
@implementation Factory01
- (id <Shape> )createProduct {
return [[Product01 alloc] init];
}
@end
抽象工厂模式(
Abstract Factory Pattern):
- 是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
- 提供了一种创建对象的最佳方式,当需要创建一组相关或互相依赖的对象时,抽象工厂模式非常有用。
- 特点:工厂方法模式中虽然解决了简单工厂模式中需要修改已有代码的问题,但当具体的产品种类变多时,就会出现大量的和他们对应的具体工厂类对象。抽象工厂模式是工厂方法模式的升级版,它用来创建一组相关或者互相依赖的对象。
代码实例
首先定义两个产品类 ;遵循并实现一个display接口 ;
objectivec
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol display <NSObject>
- (void)display ;
@end
NS_ASSUME_NONNULL_END
objectivec
#import <Foundation/Foundation.h>
#import "display.h"
NS_ASSUME_NONNULL_BEGIN
@interface FstButton : NSObject <display>
- (void)display ;
@end
NS_ASSUME_NONNULL_END
//
#import "FstButton.h"
@implementation FstButton
- (void)display {
NSLog(@"1") ;
}
@end
objectivec
#import <Foundation/Foundation.h>
#import "display.h"
NS_ASSUME_NONNULL_BEGIN
@interface SedButton : NSObject <display>
- (void)display ;
@end
NS_ASSUME_NONNULL_END
//
#import "SedButton.h"
@implementation SedButton
- (void)display {
NSLog(@"2") ;
}
@end
定义两个产品的具体工厂类;它们遵循并实现协议中定义的createProduct接口 ;
objectivec
#import <Foundation/Foundation.h>
#import "display.h"
NS_ASSUME_NONNULL_BEGIN
@protocol CreateProduct <NSObject>
- (id <display>) createProduct ;
@end
NS_ASSUME_NONNULL_END
objectivec
#import <Foundation/Foundation.h>
#import "CreateProduct.h"
#import "FstButton.h"
NS_ASSUME_NONNULL_BEGIN
@interface FstFactory : NSObject <CreateProduct>
- (id <display>) createProduct ;
@end
NS_ASSUME_NONNULL_END
//
#import "FstFactory.h"
@implementation FstFactory
- (id <display>) createProduct {
return [[FstButton alloc] init];
}
@end
objectivec
#import <Foundation/Foundation.h>
#import "CreateProduct.h"
#import "SedButton.h"
NS_ASSUME_NONNULL_BEGIN
@interface SedFactory : NSObject <CreateProduct>
- (id <display>) createProduct ;
@end
NS_ASSUME_NONNULL_END
//
#import "SedFactory.h"
@implementation SedFactory
- (id <display>)createProduct {
return [[SedButton alloc] init];
}
@end
定义一个超级工厂类来创建具体工厂类
objectivec
#import <Foundation/Foundation.h>
#import "FstFactory.h"
#import "SedFactory.h"
NS_ASSUME_NONNULL_BEGIN
@interface BaseFactory : NSObject
+ (id <CreateProduct>) createFactory : (NSString*) type ;
@end
NS_ASSUME_NONNULL_END
//
#import "BaseFactory.h"
@implementation BaseFactory
+ (id <CreateProduct>) createFactory:(NSString *)type {
if ([type isEqualToString:@"1"]) {
return [[FstFactory alloc] init] ;
} else if ([type isEqualToString:@"2"]) {
return [[SedFactory alloc] init] ;
} else {
return nil;
}
}
@end