有人说设计模式大致总结为23种,有人说29种,各式各样。我们讨论的不限于23种,关键掌握的是一些常用的设计模式。编程时一种技术,更加是一门艺术。不能只满足于写完代码运行结果正确就完事,时常考虑如何让那个代码更加简练,更加容易维护,容易扩展和复用,只有这样才能真正提高。
一 简单工厂设计模式
用单独的一个类来做这个创造实力的过程,这就是工厂类。父类A,子类B和C,子类B和C都用工厂类创建 出来,并赋值给父类A。再用父类A调用父类的方法Operation。当然子类B和C都重写了A,这个时候,如果是实例化的是谁真正调用的就是谁的operation。而不会因为是父类A接收就调用A的operation。简单来说简单工厂模式就是创建实例的一个过程。【简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现】
二.策略模式
定义一系列的算法,把每一个算法封装起来,写成一个单独的类。本模式使得算法可独立于使用它的客户而变化(也成为政策模式)。策略模式把对象本身和运算规则区分开来。
说一个使用场景可以更容易帮大家理解:我们在验证用户输入的表单的时候,加入包括电话输入框的验证和邮件输入框的验证,这两部分的验证算法是不同的,如果把这个算法看成一个函数,他几乎有相同的输入参数和返回参数。我们可以把这个相同的函数可以抽象为基类(InputValidator)的一个方法(bool validateInput(input,error)),然后抽象出两个具体的策略类:电话验证类(PhoneValidator)和邮件验证类(EmailValidator),他们需要在各自的实现里面去复写父类的验证方法(多态)。为了能够正常的调用到验证类的验证方法,我们需要自定义一个UITextField的子类CustomTextField,其中有一个InputValidator类型的引用和一个validate方法,该方法里面调用InputValidator的验证方法,然后在textFieldDidEndEditing代理方法里面调用CustomTextField的validate方法,这样就不用我们在判断输入是否合法的时候通过if else去处理每种逻辑,而且这样做方便扩展,提高可复用性。
如下图所示contetxInterface就如同是UITextField的接口,而AlgorithInterface是InputValidator这个基类,内部一个用于计算的实例方法,而ConcreteStrategyA,ConcreteStrategyB和ConcreteStrategyC都是抽象出来的子类,内部分别重写父类的用于计算的实例方法,利用多态特性,在需要的地方,生成对应的子类实例,再调用自身重写的用于计算的方法。完美的实现了策略模式。体现了面向对象的封装,继承,多态三大特性。
项目中下个版本要对签证的联系人姓名输入做一些b比较复杂的限制功能,可以尝试写一个策略模式来玩玩。
三,装饰模式
装饰模式是在不修改原来代码的情况下动态的给对象增加新的行为和职责,它通过一个对象包装被装饰对象的方法来修改类的行为,这种方法可以做为子类化的一种替代方法。
在Objective-C中,存在两种非常常见的实现:Category(类别)。
Category(类别)是一种不需要子类化就可以让你能动态的给已经存在的类增加方法的强有力的机制。新增的方法是在编译期增加的,这些方法执行的时候和被扩展的类的其它方法是一样的。它可能与装饰设计模式的定义稍微有点不同,因为Category(类别)不会保存被扩展类的引用。
实例
接下来,通过Object-C来实践一下,我设想一个场景,用Decorator模式来实现一下对某个手机的GPS和蓝牙功能扩展 首先,我们需要一个手机的接口或者抽象类,我这里就用抽象类来实现,代码如下:
@interface AbstractCellPhone : NSObject
- (NSString *)callNumber;
- (NSString *)sendMessage;
@end
#import "AbstractCellPhone.h"
@implementation AbstractCellPhone
- (NSString *)callNumber
{
return @"phone call somebody";
}
- (NSString *)sendMessage
{
return @"phone send a message to somebody";
}
@end
AbstractCellPhone也就是结构图中的Component,然后,我再来实现Nokia和Moto的手机类,这类要继承AbstractCellPhone,也就是图中ConcreteComponent类要继承Component,实现代码如下:
#import "AbstractCellPhone.h"
@interface NokiaPhone : AbstractCellPhone
@end
#import "NokiaPhone.h"
@implementation NokiaPhone
- (NSString *)callNumber
{
return @"NokiaPhone call somebody";
}
- (NSString *)sendMessage
{
return @"NokiaPhone send Message to Somebody";
}
@end
接下来我需要一个Decorator接口或者抽象类,实现代码如下:
#import "AbstractCellPhone.h"
@interface Decorator : AbstractCellPhone
{
@protected AbstractCellPhone *abstractCellPhone;
}
-(void)SetComponents:(Components*)component;
@end
#import "Decorator.h"
@implementation Decorator
-(void)SetComponents:(Components*)component{
components = component;
}
- (NSString *)callNumber
{
return components.callNumber;
}
- (NSString *)sendMessage
{
return components.sendMessage;
}
@end
正如结构图中,这个Decorator即继承了AbstractCellPhone,又包含了一个私有的AbstractCellPhone的对象。这样做的意义是:Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,它们要继承自Decorator,代码如下:
#import "Decorator.h"
@interface DecoratorGPS : Decorator
@end
#import "DecoratorGPS.h"
@implementation DecoratorGPS
- (NSString *)callNumber
{
return [NSString stringWithFormat:@"%@ with GPS", [super callNumber]];
}
- (NSString *)sendMessage
{
return [NSString stringWithFormat:@"%@ with GPS", [super sendMessage]];
}
@end
最后,用客户端程序验证一下:
int main(int argc, const char *argv[])
{
@autoreleasepool {
Components *phone = [[ConcreteComponent alloc] init];
NSLog(@"%@",phone.callNumber);
NSLog(@"%@",phone.sendMessage);
ConcreteDecoratorA *GPS = [[ConcreteDecoratorA alloc] init];
[GPS SetComponents:phone];
NSLog(@"%@",GPS.callNumber);
NSLog(@"%@",GPS.sendMessage);
ConcreteDecoratorB *bluetooth = [[ConcreteDecoratorB alloc] init];
[bluetooth SetComponents:phone];
NSLog(@"%@",bluetooth.callNumber);
NSLog(@"%@",bluetooth.sendMessage);
}
return 0;
}
执行结果:
NokiaPhone call somebody标签:NokiaPhone,软件设计,模式,callNumber,NSString,sendMessage,AbstractCellPhone,Decorator From: https://blog.51cto.com/u_15952281/6042133
NokiaPhone send Message to Somebody
NokiaPhone call somebody with GPS
NokiaPhone send Message to Somebody with GPS
NokiaPhone call somebody with BlueTooth
NokiaPhone send Message to Somebody with BlueTooth