健身餐的网站怎么做,高清品牌网站设计建设,html商品展示页面,广告图案大全图片素材文章目录 前言设计模式的三大原则简单工厂模式工厂方法模式抽象工厂模式关于三兄弟的升级与降级注意 前言
上文讲完了iOS的架构模式#xff0c;接下来聊一聊设计模式#xff0c;设计模式有许多#xff0c;主要介绍一下工厂模式
设计模式的三大原则
S 单一职责原则 告诉我… 文章目录 前言设计模式的三大原则简单工厂模式工厂方法模式抽象工厂模式关于三兄弟的升级与降级注意 前言
上文讲完了iOS的架构模式接下来聊一聊设计模式设计模式有许多主要介绍一下工厂模式
设计模式的三大原则
S 单一职责原则 告诉我们实现类要职责单一 例如UIView负责处理事件传递响应CALayer负责动画与视图的显示O 开闭原则是总纲它告诉我们要对扩展开放对修改关闭
// 基本的绘制类
interface Shape : NSObject
- (void)draw;
end// 扩展新的形状无需修改现有代码
interface Circle : Shape
endimplementation Circle
- (void)draw {// 绘制圆形的逻辑
}
endL 里氏替换原则告诉我们不要破坏继承体系
interface Bird : NSObject
- (void)fly;
endinterface Duck : Bird
endimplementation Duck
- (void)fly {// 实现飞行
}
endD 迪米特法则。 一个对象应当对其他对象尽可能少的了解实现高聚合、低耦合
// 班级类
interface Class : NSObject
- (NSArray *)getAllStudents;
end// 学校类
interface School : NSObject
property (strong, nonatomic) Class *class;
- (NSArray *)getAllStudentsInClass;
endimplementation School
- (NSArray *)getAllStudentsInClass {return [self.class getAllStudents];
}
endI 接口隔离原则 使用多个专门的协议、而不是一个庞大臃肿的协议
protocol Printer
- (void)printDocument;
endprotocol Scanner
- (void)scanDocument;
endinterface MultiFunctionMachine : NSObject Printer, Scanner
endimplementation MultiFunctionMachine
- (void)printDocument {// 打印文档
}- (void)scanDocument {// 扫描文档
}
endD 依赖倒置原则。抽象不应该依赖于具体实现、具体实现可以依赖于抽象。 调用接口感觉不到内部是如何操作的
定义协议接口
首先我们定义一个文件读取的协议这个协议负责声明读取文件内容的方法。
// FileReaderProtocol.h
#import Foundation/Foundation.hprotocol FileReaderProtocol NSObject
- (NSString *)readContent;
end具体实现类
接下来实现这个协议。这里我们可以有多种实现方式例如从本地文件系统读取或是从网络获取。
// LocalFileReader.h
#import Foundation/Foundation.h
#import FileReaderProtocol.hinterface LocalFileReader : NSObject FileReaderProtocol
property (strong, nonatomic) NSString *filePath;
- (instancetype)initWithFilePath:(NSString *)filePath;
end// LocalFileReader.m
#import LocalFileReader.himplementation LocalFileReader- (instancetype)initWithFilePath:(NSString *)filePath {self [super init];if (self) {_filePath filePath;}return self;
}- (NSString *)readContent {NSError *error;NSString *content [NSString stringWithContentsOfFile:self.filePathencoding:NSUTF8StringEncodingerror:error];if (error) {NSLog(Error reading file: %, error.localizedDescription);return nil;}return content;
}end简单工厂模式
简单工厂模式并不是一个正式的设计模式更多的是一种变成习惯 其主要通过传入参数给唯一的工厂类来创建不同类型的对象
但是这样就会出现一个问题当我们需要添加新的类型也就是添加新的产品时我们必须去修改工厂类这就违反了开闭原则
// 创建产品协议
protocol Product NSObject
- (void)use;
end// 具体产品A
interface ProductA : NSObject Product
- (void)use;
endimplementation ProductA
- (void)use {NSLog(Using Product A);
}
end// 具体产品B
interface ProductB : NSObject Product
- (void)use;
endimplementation ProductB
- (void)use {NSLog(Using Product B);
}
end// 简单工厂
interface ProductFactory : NSObject(idProduct)productWithType:(NSString *)type;
endimplementation ProductFactory(idProduct)productWithType:(NSString *)type {if ([type isEqualToString:A]) {return [ProductA new];} else if ([type isEqualToString:B]) {return [ProductB new];}return nil;
}
end// 使用
ProductFactory *factory [ProductFactory new];
idProduct productA [ProductFactory productWithType:A];
[productA use];
// 首先创建一个工厂根据传入的参数觉得工厂生产什么产品工厂方法模式
工厂方法模式同样只是生产一种产品但是一种产品可以有多个品牌
举个例子我们的可乐工厂可以生产可乐其即可以生产百事可乐也可以生产可口可乐
首先我们需要定义一个创建对象的接口但让子类决定要实例化的类是哪一个。工厂方法让类的实例化延迟到子类进行。 也就是抽象工厂是父类具体工厂是子类只有确定了具体工厂才能决定生产的产品是哪一种品牌的
// 定义产品接口
protocol Logger NSObject
- (void)logMessage:(NSString *)message;
end// 具体产品类 FileLogger
interface FileLogger : NSObject Logger
- (void)logMessage:(NSString *)message;
endimplementation FileLogger
- (void)logMessage:(NSString *)message {NSLog(File logger: %, message);
}
end// 具体产品类 NetworkLogger
interface NetworkLogger : NSObject Logger
- (void)logMessage:(NSString *)message;
endimplementation NetworkLogger
- (void)logMessage:(NSString *)message {NSLog(Network logger: %, message);
}
end// 抽象工厂类
interface LoggerFactory : NSObject
- (idLogger)createLogger;
end// 具体工厂类 FileLoggerFactory
interface FileLoggerFactory : LoggerFactory
- (idLogger)createLogger;
endimplementation FileLoggerFactory
- (idLogger)createLogger {return [[FileLogger alloc] init];
}
end// 具体工厂类 NetworkLoggerFactory
interface NetworkLoggerFactory : LoggerFactory
- (idLogger)createLogger;
endimplementation NetworkLoggerFactory
- (idLogger)createLogger {return [[NetworkLogger alloc] init];
}
end// 使用
LoggerFactory *factory;
if (useFileLogging) {factory [[FileLoggerFactory alloc] init];
} else {factory [[NetworkLoggerFactory alloc] init];
}
idLogger logger [factory createLogger];
[logger logMessage:This is a test log.];在这个例子中LoggerFactory 是一个抽象类定义了一个名为 createLogger 的方法但并没有实现它。这个方法的具体实现由 FileLoggerFactory 和 NetworkLoggerFactory 这两个子类根据不同的业务逻辑来提供。这样每个工厂子类决定了要实例化的具体 Logger 类父类不需要知道具体的实现细节。
这种模式的优势在于它支持易于扩展和修改的开放封闭原则同时减少了类间的耦合。
我们再来看一个场景 假设我们正在开发一个简单的绘图应用该应用可以绘制不同类型的图形。我们可以使用工厂方法模式来创建不同类型的图形对象。
步骤 1: 定义图形接口和具体图形类。
// Shape.h
#import Foundation/Foundation.hprotocol Shape NSObject
- (void)draw;
end// Circle.h
#import Shape.hinterface Circle : NSObject Shape
endimplementation Circle
- (void)draw {NSLog(Drawing a circle.);
}
end// Rectangle.h
#import Shape.hinterface Rectangle : NSObject Shape
endimplementation Rectangle
- (void)draw {NSLog(Drawing a rectangle.);
}
end步骤 2: 定义抽象工厂类和具体工厂类。
// ShapeFactory.h
#import Foundation/Foundation.h
#import Shape.hinterface ShapeFactory : NSObject
- (idShape)createShape;
end// CircleFactory.h
#import ShapeFactory.h
#import Circle.hinterface CircleFactory : ShapeFactory
endimplementation CircleFactory
- (idShape)createShape {return [[Circle alloc] init];
}
end// RectangleFactory.h
#import ShapeFactory.h
#import Rectangle.hinterface RectangleFactory : ShapeFactory
endimplementation RectangleFactory
- (idShape)createShape {return [[Rectangle alloc] init];
}
end步骤 3: 使用工厂类。
// main.m
#import Foundation/Foundation.h
#import CircleFactory.h
#import RectangleFactory.hint main(int argc, const char * argv[]) {autoreleasepool {// 创建圆形工厂和矩形工厂ShapeFactory *circleFactory [[CircleFactory alloc] init];ShapeFactory *rectangleFactory [[RectangleFactory alloc] init];// 使用工厂方法创建形状idShape circle [circleFactory createShape];idShape rectangle [rectangleFactory createShape];// 绘制形状[circle draw];[rectangle draw];}return 0;
}主程序依赖于抽象接口Shape 协议和 ShapeFactory 类而不是具体的类
我们来理解一下这句话
想象我们正在开发一个图形软件软件需要支持多种类型图形我们此时不需要知道操作的图形具体是什么使用接口来定义这些操作可以让你的软件支持任意类型的图形
定义抽象接口如 Shape
protocol Shape NSObject
- (void)draw;
end实现具体类如 Circle 和 Rectangle
interface Circle : NSObject Shape
endimplementation Circle
- (void)draw {NSLog(Drawing a circle.);
}
endinterface Rectangle : NSObject Shape
endimplementation Rectangle
- (void)draw {NSLog(Drawing a rectangle.);
}
endCircle 和 Rectangle 类都实现了 Shape 协议但具体的绘制逻辑根据图形的类型不同而不同。
抽象工厂模式
抽象工厂模式与工厂模式关键区别在于抽象工厂是用来创建一系列产品的每个产品可以属于不同的产品类别而工厂方法一般只创建一种产品。
场景 假设我们有一个应用程序需要支持多种界面风格如“暗黑模式”和“亮色模式”每种风格都有一套不同的界面组件如按钮、文本框等。我们可以使用抽象工厂模式来根据用户的选择动态提供相应的组件。
步骤 1: 定义抽象产品和具体产品
首先我们定义两种产品接口Button 和 TextField以及它们的具体实现。
// Button.h
protocol Button NSObject
- (void)display;
end// DarkButton.h
#import Button.hinterface DarkButton : NSObject Button
endimplementation DarkButton
- (void)display {NSLog(Displaying dark button);
}
end// LightButton.h
#import Button.hinterface LightButton : NSObject Button
endimplementation LightButton
- (void)display {NSLog(Displaying light button);
}
end// TextField.h
protocol TextField NSObject
- (void)display;
end// DarkTextField.h
#import TextField.hinterface DarkTextField : NSObject TextField
endimplementation DarkTextField
- (void)display {NSLog(Displaying dark text field);
}
end// LightTextField.h
#import TextField.hinterface LightTextField : NSObject TextField
endimplementation LightTextField
- (void)display {NSLog(Displaying light text field);
}
end步骤 2: 定义抽象工厂和具体工厂
定义一个抽象工厂接口GUIFactory以及为每种界面风格实现一个具体工厂。
// GUIFactory.h
#import Button.h
#import TextField.hprotocol GUIFactory NSObject
- (idButton)createButton;
- (idTextField)createTextField;
end// DarkGUIFactory.h
#import GUIFactory.h
#import DarkButton.h
#import DarkTextField.hinterface DarkGUIFactory : NSObject GUIFactory
endimplementation DarkGUIFactory
- (idButton)createButton {return [DarkButton new];
}
- (idTextField)createTextField {return [DarkTextField new];
}
end// LightGUIFactory.h
#import GUIFactory.h
#import LightButton.h
#import LightTextField.hinterface LightGUIFactory : NSObject GUIFactory
endimplementation LightGUIFactory
- (idButton)createButton {return [LightButton new];
}
- (idTextField)createTextField {return [LightTextField new];
}
end步骤 3: 使用抽象工厂
客户端代码现在可以根据用户的偏好选择使用合适的工厂而不需要关心具体的产品如何创建。
// main.m
#import Foundation/Foundation.h
#import DarkGUIFactory.h
#import LightGUIFactory.hint main(int argc, const char * argv[]) {autoreleasepool {idGUIFactory factory;BOOL useDarkMode YES; // 用户选择使用暗黑模式if (useDarkMode) {factory [[DarkGUIFactory alloc] init];} else {factory [[LightGUIFactory alloc] init];}idButton button [factory createButton];idTextField textField [factory createTextField];[button display];[textField display];}return 0;
}关于三兄弟的升级与降级
单一类型产品比较少时用简单工厂模式。单一类型产品各种定制比较多时用工厂模式。多种类型产品时使用抽象工厂模式。
注意
我们注意到定义产品类前我们通常会先定义一个抽象产品接口也就是协议例如
// 定义产品接口
protocol Logger NSObject
- (void)logMessage:(NSString *)message;
end// 具体产品类 FileLogger
interface FileLogger : NSObject Logger
- (void)logMessage:(NSString *)message;
end同时还有在主程序中创建对象
// 使用工厂方法创建形状idShape circle [circleFactory createShape];idShape rectangle [rectangleFactory createShape];这就符合我们的依赖倒置原则
主程序依赖于抽象接口Shape 协议和 ShapeFactory 类而不是具体的类