今天和大家分享的是桥接模式。在介绍桥接模式之前先和大家分享一个原则,那就是合成/聚合复用原则,具体定义是这样的:
合成/聚合复用原则(CAPP),尽量使用合成/聚合,尽量不要使用类继承。
合成(Composition,也有翻译成组合)和聚合(Aggregation)都是关联的特殊种类。聚合表示一种弱的‘拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。打个比方说,小鸟有两个翅膀,翅膀与小鸟是部分和整体的关系,并且它们的生命周期是相同的,于是翅膀和小鸟就是合成关系。然而相对于鸟群来说,一个鸟群有多只小鸟,所以小鸟和鸟群是聚合关系。合成/聚合复用原则的好处是,优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
那么,说这个原则的目的是什么呢?呵呵,其实今天所要说的桥接模式就是遵循这个原则的。下面给出桥接模式的定义。
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。
这里说明一下,什么叫抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。举个例子,当我们封装手机软件类的时候,如果把手机软件整体抽象类作为根类,那么当我们往下细分的时候,比如我们可以派生出通讯录类,那么这个通讯录类再往下派生出各个品牌上的通讯录类,以此类推,每当我们要从手机软件类派生出一个新软件时又需要重复派生之前已有的手机品牌的派生类。如此一来我们就做了很多无用功而且日积月累,很容易会变成一个庞然大物,而且也破坏了开放封闭原则。
说了半天反面的例子,其实目的就是为了说明桥接模式要解决的问题是什么,呵呵。下面先给出桥接模式的类结构图。
从这张图中,我们可以类比之前描述的那个例子,按照桥接模式重新把类进行划分。比如这里的Abstraction可以对应到手机品牌,RefinedAbstraction是派生的各个手机品牌,Implementor可以对应手机软件,其派生类ConcreteImplementorA和ConcreteImplementorB可以对应通讯录类和游戏类,这样划分就可以保证它们各自的变化不会影响其他实现,从而达到应对变化的目的,当然也避免了之前说的超级庞大的结构。
其实,桥接模式的价值在于当实现系统可能有多角度分类时,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
说了这么多,给大家简单展示一下代码实现。
-
Implementor类接口
1
2
3
4
5
|
#import <Foundation/Foundation.h>
@interface
Implementor:
NSObject
-(
void
)Operation;
@end
|
-
Implementor类实现
1
2
3
4
5
6
7
|
#import "Implementor.h"
@implementation
Implementor
-(
void
)Operation{
return
;
}
@end
|
-
ConcreteImplementorA类接口
1
2
3
4
|
#import "Implementor.h"
@interface
ConcreteImplementorA :Implementor
@end
|
-
ConcreteImplementorA类实现
1
2
3
4
5
6
7
|
#import "ConcreteImplementorA.h"
@implementation
ConcreteImplementorA
-(
void
)Operation{
NSLog
(@
"具体实现A的方法执行"
);
}
@end
|
-
ConcreteImplementorB类接口
1
2
3
4
|
#import "Implementor.h"
@interface
ConcreteImplementorB:Implementor
@end
|
-
ConcreteImplementorB类实现
1
2
3
4
5
6
7
|
#import "ConcreteImplementorB.h"
@implementation
ConcreteImplementorB
-(
void
)Operation{
NSLog
(@
"具体实现B的方法执行"
);
}
@end
|
-
Abstraction类接口
1
2
3
4
5
6
7
8
9
|
#import <Foundation/Foundation.h>
@class
Implementor;
@interface
Abstraction :
NSObject
{
Implementor *myImplementor;
}
-(
void
)SetImplementor:(Implementor*)implementor;
-(
void
)Operation;
@end
|
-
Abstraction类实现
1
2
3
4
5
6
7
8
9
10
11
|
#import "Abstraction.h"
#import "Implementor.h"
@implementation
Abstraction
-(
void
)SetImplementor:(Implementor *)implementor{
myImplementor = implementor;
}
-(
void
)Operation{
[myImplementor Operation];
}
@end
|
-
RefinedAbstraction类接口
1
2
3
4
|
#import "Abstraction.h"
@interface
RefinedAbstraction:Abstraction
@end
|
-
RefinedAbstraction类实现
1
2
3
4
5
6
7
8
|
#import "RefinedAbstraction.h"
#import "Implementor.h"
@implementation
RefinedAbstraction
-(
void
)Operation{
[myImplementor Operation];
}
@end
|
-
Main方法调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#import <Foundation/Foundation.h>
#import "RefinedAbstraction.h"
#import "ConcreteImplementorA.h"
#import "ConcreteImplementorB.h"
int
main(
int
argc,
const
char
* argv[])
{
@autoreleasepool
{
Abstraction *ab = [RefinedAbstraction
new
];
[ab SetImplementor:[ConcreteImplementorA
new
]];
[ab Operation];
[ab SetImplementor:[ConcreteImplementorB
new
]];
[ab Operation];
}
return
0;
}
|
完毕!简单做了一个代码的展示。其实我倒是觉得,这个模式更多的是想说,多聚合少继承!