使用目的:
让使用它的人认为它们是同一个类别的物件例子:
档案系统(树状图),如下图的UML所画的(图的来源是随便找的),File、Directory都是继承于Entry,
外面的人只需要操作Entry就能同时使用不同类别的物件,File与Directory针对各自的特性去实作它们的方法,
而不是Entry,不过若是共有属性,就可以直接在Entry里面实作
针对上图我简单做一个很简陋的档案浏览器Demo,来练习这种组合模式
首先我建立了FileComposite类别来当做上图的Etnry,
然后建立了ComFile、ComDirectory去继承FileComposite如下:
//FileComposite.h
@interface FileComposite : NSObject
@property(strong, nonatomic) NSString* file_name;
@property(strong, nonatomic) NSString* file_size;
@property(strong, nonatomic) NSDate* modification_date;
@property(assign, nonatomic) EntryType entry_type;
@property(strong, nonatomic) NSString* file_path;
-(FileComposite*) initWithPath:(NSString*)path;
-(void) add:(FileComposite*)c;
-(NSArray*) subItems;
@end
@interface ComFile : FileComposite
@end
@interface ComDirectory : FileComposite
@end
//FileComposite.m
@implementation FileComposite
-(FileComposite*) initWithPath:(NSString*)path{
self = [super init];
if (self) {
self.file_path = path;
self.file_name = [path lastPathComponent];
NSString* full_path = [[[ComFilesBrowserMgr getInstance] getBaseURLString] stringByAppendingPathComponent:path];
self.attributesDic =[[NSFileManager defaultManager] attributesOfItemAtPath:full_path error:nil];
self.modification_date = [self.attributesDic fileModificationDate];
}
return self;
}
-(void) add:(FileComposite*)c{
//不实作
}
-(NSArray*) subItems{
//不实作
return nil;
}
@end
@implementation ComFile
-(FileComposite*) initWithPath:(NSString*)path{
self = [super initWithPath:path];
if (self) {
self.entry_type = kEntryTypeGeneric;
//将档案大小转换成文字KB、MB、GB之类的
long long fileSize = [self.attributesDic fileSize];
if (fileSize==0) {
self.file_size= @"0 KB";
}
else{
self.file_size=[NSByteCountFormatter stringFromByteCount:fileSize countStyle:NSByteCountFormatterCountStyleFile];
}
}
return self;
}
-(void) add:(FileComposite*)c{
//不实作
}
-(NSArray*) subItems{
//不实作
return nil;
}
@end
@interface ComDirectory ()
@property(strong, nonatomic) NSMutableArray* children;
@end
@implementation ComDirectory
-(FileComposite*) initWithPath:(NSString*)path{
self = [super initWithPath:path];
if (self) {
self.entry_type = kEntryTypeDirectory;
}
return self;
}
-(NSMutableArray*) children{
if (!_children) {
_children = [@[]mutableCopy];
}
return _children;
}
-(void) add:(FileComposite*)c{
//加入子项目
[self.children addObject:c];
}
-(NSArray*) subItems{
return self.children;
}
@end
然后当需要一个找寻一个目录里面的内容时,就利用这种组合做出一个 FileComposite出来
ComDirectory* parentCom = [[ComDirectory alloc] initWithPath:relativePath];
for (NSString* path in contents){
NSString* source_path = [relativePath stringByAppendingPathComponent:path];
NSString* full_path = [self.rootPath stringByAppendingPathComponent:source_path];
if ([self isDirectoryAtURLString:full_path]){
//将directory加入parent里
ComDirectory* directory=[[ComDirectory alloc] initWithPath:source_path];
[parentCom add:directory];
}
else{
//将file加入parent里
ComFile* file=[[ComFile alloc] initWithPath:source_path];
[parentCom add:file];
}
}
}
得到FileComposite之後,只需要
FileComposite* entry= [[ComFilesBrowserMgr getInstance] loadFilesListAtDir:self.currentPath];
NSArray* subItems =[entry subItems];
sumItems就是指定目录底下的项目内容
最后附上小Demo
https://github.com/joyce-328/CompositePattern.git