ロゴ
ホーム 提案事例 Obxetoについて 問い合わせ

1. Composite Pattern

1.1 特徴

Composite Patternは、構成要素(Component)とその合成物(Composite)の構造を表現し、 双方に共通な操作を提供するDesign Patternです。

1.2 サンプルプログラムを書いた目的

UMLで記述されたComposite PatternをObjective-Cで可能な限り忠実に記述する。特に共通の操作を 提供する点で確実にLeafとCompositeにその操作が実装されるようにする。

1.3 UMLとクラス定義

家族構成を表現するためのクラス群を以下のように定義した。 このクラス群により家族の中の親と子供や家族の中の家族を表現可能になっている。

図1-1:クラス図

  • FamilyMemberクラス(Component):共通の操作を定義
  • Parentクラス(Leaf):
  • Childクラス(Leaf):
  • Familyクラス(Composite):様々な家族構成を持つ家族

1.4 サンプルプログラム

        #import <Foundation/Foundation.h>

        /* 家族の成員:FamilyMember */
        @protocol FamilyMember
        - (void)printWithDepth:(int)depth;
        @end

        /* 親:Parent */
        @interface Parent : NSObject<FamilyMember>
        {
            NSString *_name;
        }
        - (id)initWithName:(NSString *)name;
        - (void)printWithDepth:(int)depth;
        @end
        @implementation Parent
        - (id)initWithName:(NSString *)name
        {
            self = [super init];
            if (self != nil) {
                _name = name;
           }
            return self;
        }
        - (void)printWithDepth:(int)depth
        {
            printf("(%s)", [_name UTF8String]);
        }
        @end
        
        /* 子:Child */
        @interface Child : NSObject<FamilyMember>
        {
            NSString *_name;
        }
        - (id)initWithName:(NSString *)name;
        - (void)printWithDepth:(int)depth;
        @end
        @implementation Child
        - (id)initWithName:(NSString *)name
        {
            self = [super init];
            if (self != nil) {
                _name = name;
            }
            return self;
        }
        - (void)printWithDepth:(int)depth
        {
            printf("(%s)", [_name UTF8String]);
        }
        @end

        /* 家族:Family */
        @interface Family : NSObject<FamilyMember>
        {
            NSMutableArray* children;
        }
        - (id)init;
        - (void)add:(id)child;
        - (void)printWithDepth:(int)depth;
        - (void)printSpaceWithDepth:(int)depth;
        @end
        @implementation Family
        - (id)init
        {
            self = [super init];
            if (self != nil) {
                children = [[[NSMutableArray alloc] init] autorelease];
            }
            return self;
        }
        - (void)add:(id)child 
        {
            [children addObject:child];
        }
        - (void)printWithDepth:(int)depth
        {
            [self printSpaceWithDepth:depth];
            printf("Family:{");
            [self printSpaceWithDepth:depth + 1];
            for (id<FamilyMember> child in children) {
                [child printWithDepth:depth + 1];
                printf(", ");
            }
            [self printSpaceWithDepth:depth];
            printf("}");
        }
        - (void)printSpaceWithDepth:(int)depth
        {
            printf("\n");
            for (int index = 0; index < depth; index++)
                printf("   ");
        }
        @end

        int main(int argc, const char * argv[])
        {
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
            
            Family<FamilyMember> *family1 = [[Family alloc] init];
            Parent<FamilyMember> *parent1 = 
                [[Parent alloc] initWithName:@"Taro, Hanako"];
            Child<FamilyMember>  *kenji   = [[Child alloc] initWithName:@"Kenji"];
            Family<FamilyMember> *family2 = [[Family alloc] init];
            Parent<FamilyMember> *parent2 = 
                [[Parent alloc] initWithName:@"Ichiro, Michiko"];
            Child<FamilyMember>  *yoshiko = [[Child alloc] initWithName:@"Yoshiko"];
            [family1 autorelease];
            [parent1 autorelease];
            [kenji   autorelease];
            [family2 autorelease];
            [parent2 autorelease];
            [yoshiko autorelease];

            [family1 add:parent1];
            [family1 add:kenji];
            [family1 add:family2];
            [family2 add:parent2];
            [family2 add:yoshiko];
            
            [family1 printWithDepth:0];
            
            [pool drain];
            
            return 0;
        }
     

参考文献: Deign Pattern by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides