结构型模式
适配器模式
模式动机
适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。
模式定义
适配器模式:将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
模式结构
适配器模式包含如下角色:
- HCDPlayer:目标抽象类
- HCDTranslator:适配器类
- HCDForeignCenter:适配者类
适配器模式类图
时序图
适配器模式时序图源码
//调用方式
HCDPlayer *forward = [[HCDForwards alloc] initWithName:@"maidi"];
[forward attack];
[forward defense];
HCDForeignCenter *foreignCenter = [[HCDForeignCenter alloc] initWithName:@"姚明"];
HCDPlayer *translator = [[HCDTranslator alloc] initWithForeigncenter:foreignCenter];
[translator attack];
[translator defense];
//HCDPlayer.h
@interface HCDPlayer : NSObject
@property (nonatomic,copy) NSString *name;
-(void)attack;
-(void)defense;
-(instancetype)initWithName:(NSString *)name;
@end
//HCDForwards.m
@implementation HCDForwards
-(void)attack{
NSLog(@"前锋%@进攻",self.name);
}
-(void)defense{
NSLog(@"前锋%@防守",self.name);
}
@end
//HCDTranslator.m
@interface HCDTranslator ()
@property(nonatomic, strong) HCDForeignCenter *foreigncenter;
@end
@implementation HCDTranslator
-(instancetype)initWithForeigncenter:(HCDForeignCenter *)foreigncenter {
self = [super init];
if (self) {
_foreigncenter = foreigncenter;
}
return self;
}
-(void)defense{
[self.foreigncenter foreignDefent];
}
-(void)attack{
[self.foreigncenter foreignAttact];
}
@end
//HCDForeignCenter.m
@implementation HCDForeignCenter
- (instancetype)initWithName:(NSString *)name{
self = [super init];
if (self) {
_name = name;
}
return self;
}
- (void)foreignAttact{
NSLog(@"外籍中锋%@进攻",self.name);
}
- (void)foreignDefent{
NSLog(@"外籍中锋%@防守",self.name);
}
@end
桥接模式
模式动机
如果需要开发一个跨平台视频播放器,可以在不同操作系统平台(如Windows、Linux、Unix等)上播放多种格式的视频文件,常见的视频格式包括MPEG、RMVB、AVI、WMV等。现使用桥接模式设计该播放器。此时至少有如下两种设计方案:
- 第一种设计方案是为每一种操作系统都提供一套支持各种视频格式的版本;
- 第二种设计方案是根据实际需要对操作系统和支持的视频格式进行组合。
对于有两个变化维度(即两个变化的原因)的系统,采用方案二来进行设计系统中类的个数更少,且系统扩展更为方便。设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。
尽量使用组合,而不要使用继承。
模式定义
桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式。
模式结构
桥接模式包含如下角色:
- Abstraction:抽象类
- RefinedAbstraction:扩充抽象类
- Implementor:实现类接口
-
ConcreteImplementor:具体实现类
桥接模式类图
时序图
桥接模式时序图源码
略
装饰模式
模式动机
一般有两种方式可以实现给一个类或对象增加行为:
- 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机;
- 关联机制,即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)。
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。
模式定义
装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。它是一种对象结构型模式。
模式结构
装饰模式包含如下角色:
- Component: 抽象构件
- ConcreteComponent: 具体构件
- Decorator: 抽象装饰类
-
ConcreteDecorator: 具体装饰类
装饰模式类图
时序图
装饰模式时序图源码
//使用示例
LTPerson *xc = [[LTPerson alloc] initWithName:@"小菜"];
NSLog(@"\n第一种装扮");
LTSneakers *sneaker = [[LTSneakers alloc] init];
LTBigTrouser *bigTrouser = [[LTBigTrouser alloc] init];
LTTshirts *tshirts = [[LTTshirts alloc] init];
[sneaker decorate:xc];
[bigTrouser decorate:sneaker];
[tshirts decorate:bigTrouser];
[tshirts show];
NSLog(@"\n第二种装扮");
LTLeatherShoes *leatherShoes = [[LTLeatherShoes alloc] init];
LTTie *tie = [[LTTie alloc] init];
LTSuit *suit = [[LTSuit alloc] init];
[leatherShoes decorate:xc];
[tie decorate:leatherShoes];
[suit decorate:tie];
[suit show];
//LTPerson.h
@interface LTPerson : NSObject
- (instancetype)initWithName:(NSString *)name;
- (void)show;
@end
//LTPerson.m
@interface LTPerson ()
@property (nonatomic, copy) NSString *name;
@end
@implementation LTPerson
- (instancetype)initWithName:(NSString *)name {
self = [super init];
if (self) {
_name = name;
}
return self;
}
- (void)show {
NSLog(@"装扮的%@",self.name);
}
@end
//LTFinery.h
@interface LTFinery : LTPerson
- (void)decorate:(LTPerson *)person;
@end
@interface LTTshirts : LTFinery
@end
@interface LTBigTrouser : LTFinery
@end
@interface LTSneakers : LTFinery
@end
@interface LTLeatherShoes : LTFinery
@end
@interface LTTie : LTFinery
@end
@interface LTSuit : LTFinery
@end
//LTFinery.m
@interface LTFinery ()
@property (nonatomic, strong) LTPerson *person;
@end
@implementation LTFinery
- (void)decorate:(LTPerson *)person {
self.person = person;
}
- (void)show {
if(self.person) {
[self.person show];
}
}
@end
@implementation LTTshirts
- (void)show {
NSLog(@"大T恤");
[super show];
}
@end
@implementation LTBigTrouser
- (void)show {
NSLog(@"垮裤");
[super show];
}
@end
@implementation LTSneakers
- (void)show {
NSLog(@"破球鞋");
[super show];
}
@end
@implementation LTLeatherShoes
- (void)show {
NSLog(@"皮鞋");
[super show];
}
@end
@implementation LTTie
- (void)show {
NSLog(@"领带");
[super show];
}
@end
@implementation LTSuit
- (void)show {
NSLog(@"西装");
[super show];
}
@end
外观模式
模式动机
为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一子系统更加容易使用。
模式定义
外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。它是一种对象结构型模式。
模式结构
外观模式包含如下角色:
- Facade: 外观角色
- SubSystem:子系统角色
时序图
外观模式时序图源码
//使用示例
HCDFound *found = [[HCDFound alloc]init];
[found buyFund];
[found sellFund];
//HCDstock.h
@interface HCDstock : NSObject<HCDStockProtocol>
@end
@interface HCDFound()
@property (nonatomic, strong) HCDstock1 *stock1;
@property (nonatomic, strong) HCDstock2 *stock2;
@property (nonatomic, strong) HCDstock3 *stock3;
@end
@implementation HCDFound
-(instancetype)init{
self = [super init];
if (self) {
_stock1 = [[HCDstock1 alloc]init];
_stock2 = [[HCDstock2 alloc]init];
_stock3 = [[HCDstock3 alloc]init];
}
return self;
}
-(void)buyFund{
[self.stock1 buy];
[self.stock2 buy];
[self.stock3 buy];
}
-(void)sellFund{
[self.stock1 sell];
[self.stock2 sell];
[self.stock3 sell];
}
享元模式
模式动机
面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。
- 享元模式正是为解决这一类问题而诞生的。享元模式通过共享技术实现相同或相似对象的重用。
- 在享元模式中可以共享的相同内容称为内部状态(IntrinsicState),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有一些不同的特征,而相同的内部状态是可以共享的。
- 在享元模式中通常会出现工厂模式,需要创建一个享元工厂来负责维护一个享元池(Flyweight Pool)用于存储具有相同内部状态的享元对象。
- 在享元模式中共享的是享元对象的内部状态,外部状态需要通过环境来设置。在实际使用中,能够共享的内部状态是有限的,因此享元对象一般都设计为较小的对象,它所包含的内部状态较少,这种对象也称为细粒度对象。享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。
模式定义
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。
模式结构
享元模式包含如下角色:
- Flyweight: 抽象享元类
- ConcreteFlyweight: 具体享元类
- UnsharedConcreteFlyweight: 非共享具体享元类
-
FlyweightFactory: 享元工厂类
享元模式类图
时序图
享元模式时序图源码
//使用示例
HCDWebSiteFactory *facoty = [[HCDWebSiteFactory alloc]init];
HCDWebSiteType fx = [facoty getWebSiteCategory:@"产品展示"];
HCDUser *user = [[HCDUser alloc]init];
user.name = @"小菜";
[fx use:user];
HCDWebSiteType fy = [facoty getWebSiteCategory:@"产品展示"];
HCDUser *user1 = [[HCDUser alloc]init];
user1.name = @"大鸟";
[fy use:user1];
HCDWebSiteType fz = [facoty getWebSiteCategory:@"博客"];
HCDUser *user2 = [[HCDUser alloc]init];
user2.name = @"咪咪";
[fz use:user2];
//HCDWebSiteFactory.h
@interface HCDWebSiteFactory : NSObject
@property(nonatomic,strong) NSDictionary *flyweights;
-(id<HCDWebSite> )getWebSiteCategory:(NSString *)webkey;
-(NSInteger)getWebSiteCount;
@end
//HCDWebSiteFactory.m
@implementation HCDWebSiteFactory
-(instancetype)init{
self = [super init];
if (self) {
_flyweights = [NSDictionary dictionary];
}
return self;
}
-(id<HCDWebSite> )getWebSiteCategory:(NSString *)webkey{
__block id<HCDWebSite> webset = nil;
[self.flyweights enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (webkey == key) {
webset = obj;
*stop = YES;
}
}];
if (webset == nil) {
HCDConcreteWebSite *concreteset = [[HCDConcreteWebSite alloc] init];
concreteset.webName = webkey;
webset = concreteset;
NSMutableDictionary *mutabledic = [NSMutableDictionary dictionaryWithDictionary:self.flyweights];
[mutabledic setObject:webset forKey:webkey];
self.flyweights = [NSDictionary dictionaryWithDictionary:mutabledic];
}
return webset;
}
-(NSInteger)getWebSiteCount{
return self.flyweights.count;
}
@end
//HCDConcreteWebSite.h
@interface HCDConcreteWebSite : NSObject<HCDWebSite>
@property(nonatomic,strong)NSString *webName;
@end
//HCDConcreteWebSite.m
@implementation HCDConcreteWebSite
-(void)use:(HCDUser *)user{
NSLog(@"网站分类:%@,用户:%@",self.webName,user.name);
}
@end
代理模式
模式动机
在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务。
模式定义
在某些情况下,一个客户不想或者不能直接引用一个对 象,此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。
模式结构
代理模式包含如下角色:
- Subject: 抽象主题角色
- Proxy: 代理主题角色
-
RealSubject: 真实主题角色
代理模式类图
时序图
代理模式时序图源码
//使用示例
HCDschoolGirl *girl = [[HCDschoolGirl alloc] init];
girl.name = @"哈哈哈哈哈";
HCDproxy *proxy = [[HCDproxy alloc] initWithSchoolGirl:girl];
[proxy giveFlowers];
[proxy giveDolls];
[proxy giveChocolate];
//HCDschoolGirl.h
@interface HCDschoolGirl : NSObject
@property(nonatomic,strong)NSString *name;
@end
//HCDgiveGift.h
@protocol HCDgiveGift <NSObject>
/// 送洋娃娃
- (void)giveDolls;
/// 送鲜花
- (void)giveFlowers;
/// 送巧克力
- (void)giveChocolate;
@end
//HCDpursuit.m
@interface HCDpursuit ()
@property(nonatomic,strong)HCDschoolGirl *schoolGirl;
@end
@implementation HCDpursuit
-(instancetype)initWithSchoolGirl:(HCDschoolGirl *)schoolGirl{
self = [super init];
if (self) {
_schoolGirl = schoolGirl;
}
return self;
}
-(void)giveChocolate{
NSLog(@"送你巧克力%@",self.schoolGirl.name);
}
-(void)giveDolls{
NSLog(@"送你洋娃娃%@",self.schoolGirl.name);
}
-(void)giveFlowers{
NSLog(@"送你玫瑰花%@",self.schoolGirl.name);
}
@end
//HCDproxy.m
@interface HCDproxy ()
@property (strong, nonatomic) HCDpursuit *pursuit;
@end
@implementation HCDproxy
- (instancetype)initWithSchoolGirl:(HCDschoolGirl *)schoolGirl {
self = [super init];
if (self) {
self.pursuit = [[HCDpursuit alloc] initWithSchoolGirl:schoolGirl];
}
return self;
}
- (void)giveDolls {
[self.pursuit giveDolls];
}
- (void)giveFlowers {
[self.pursuit giveFlowers];
}
- (void)giveChocolate {
[self.pursuit giveChocolate];
}
@end
网友评论