Prototype Design Pattern

1. 위젯 테마/스타일 복제

dart

class ButtonStyle implements Cloneable<ButtonStyle> {
  final Color backgroundColor;
  final Color textColor;
  final double borderRadius;
  final EdgeInsets padding;
  
  ButtonStyle({
    required this.backgroundColor,
    required this.textColor,
    required this.borderRadius,
    required this.padding,
  });
  
  @override
  ButtonStyle clone() {
    return ButtonStyle(
      backgroundColor: backgroundColor,
      textColor: textColor,
      borderRadius: borderRadius,
      padding: padding,
    );
  }
  
  // 특정 속성만 변경하는 메서드
  ButtonStyle copyWith({
    Color? backgroundColor,
    Color? textColor,
    double? borderRadius,
    EdgeInsets? padding,
  }) {
    return ButtonStyle(
      backgroundColor: backgroundColor ?? this.backgroundColor,
      textColor: textColor ?? this.textColor,
      borderRadius: borderRadius ?? this.borderRadius,
      padding: padding ?? this.padding,
    );
  }
}

// 사용법
ButtonStyle primaryStyle = ButtonStyle(
  backgroundColor: Colors.blue,
  textColor: Colors.white,
  borderRadius: 8.0,
  padding: EdgeInsets.all(16),
);

// 기본 스타일을 복제해서 변형
ButtonStyle secondaryStyle = primaryStyle.copyWith(
  backgroundColor: Colors.grey,
);
ButtonStyle dangerStyle = primaryStyle.copyWith(
  backgroundColor: Colors.red,
);

2. 게임 아이템/캐릭터 복제

dart

abstract class Cloneable<T> {
  T clone();
}

class GameCharacter implements Cloneable<GameCharacter> {
  String name;
  int level;
  int hp;
  int mp;
  List<String> skills;
  Map<String, int> stats;
  
  GameCharacter({
    required this.name,
    required this.level,
    required this.hp,
    required this.mp,
    required this.skills,
    required this.stats,
  });
  
  @override
  GameCharacter clone() {
    return GameCharacter(
      name: name,
      level: level,
      hp: hp,
      mp: mp,
      skills: List.from(skills), // 깊은 복사
      stats: Map.from(stats),    // 깊은 복사
    );
  }
}

// 사용법: RPG 게임에서 몬스터 생성
class MonsterFactory {
  static final Map<String, GameCharacter> _templates = {
    'goblin': GameCharacter(
      name: 'Goblin',
      level: 1,
      hp: 50,
      mp: 10,
      skills: ['Attack', 'Run'],
      stats: {'strength': 8, 'defense': 5},
    ),
    'orc': GameCharacter(
      name: 'Orc',
      level: 5,
      hp: 120,
      mp: 20,
      skills: ['Heavy Attack', 'Roar'],
      stats: {'strength': 15, 'defense': 10},
    ),
  };
  
  static GameCharacter createMonster(String type) {
    final template = _templates[type];
    if (template == null) throw Exception('Unknown monster type');
    return template.clone(); // 템플릿 복제
  }
}

// 게임에서 사용
GameCharacter goblin1 = MonsterFactory.createMonster('goblin');
GameCharacter goblin2 = MonsterFactory.createMonster('goblin');
// 각각 독립적인 인스턴스

3. 복잡한 UI 설정 복제

dart

class ChatBubbleConfig implements Cloneable<ChatBubbleConfig> {
  final Color backgroundColor;
  final Color textColor;
  final BorderRadius borderRadius;
  final EdgeInsets margin;
  final EdgeInsets padding;
  final TextStyle textStyle;
  final bool showTimestamp;
  final bool showAvatar;
  
  ChatBubbleConfig({
    required this.backgroundColor,
    required this.textColor,
    required this.borderRadius,
    required this.margin,
    required this.padding,
    required this.textStyle,
    required this.showTimestamp,
    required this.showAvatar,
  });
  
  @override
  ChatBubbleConfig clone() {
    return ChatBubbleConfig(
      backgroundColor: backgroundColor,
      textColor: textColor,
      borderRadius: borderRadius,
      margin: margin,
      padding: padding,
      textStyle: textStyle,
      showTimestamp: showTimestamp,
      showAvatar: showAvatar,
    );
  }
  
  ChatBubbleConfig copyWith({
    Color? backgroundColor,
    Color? textColor,
    // ... 다른 속성들
  }) {
    return ChatBubbleConfig(
      backgroundColor: backgroundColor ?? this.backgroundColor,
      textColor: textColor ?? this.textColor,
      // ... 나머지 속성들
      borderRadius: borderRadius,
      margin: margin,
      padding: padding,
      textStyle: textStyle,
      showTimestamp: showTimestamp,
      showAvatar: showAvatar,
    );
  }
}

// 사용법: 채팅 앱에서 메시지 스타일
class ChatTheme {
  static final ChatBubbleConfig baseConfig = ChatBubbleConfig(
    backgroundColor: Colors.grey[200]!,
    textColor: Colors.black,
    borderRadius: BorderRadius.circular(12),
    margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
    padding: EdgeInsets.all(12),
    textStyle: TextStyle(fontSize: 16),
    showTimestamp: true,
    showAvatar: true,
  );
  
  // 내 메시지 스타일
  static ChatBubbleConfig get myMessage => baseConfig.copyWith(
    backgroundColor: Colors.blue[500],
    textColor: Colors.white,
  );
  
  // 상대방 메시지 스타일
  static ChatBubbleConfig get otherMessage => baseConfig.clone();
  
  // 시스템 메시지 스타일
  static ChatBubbleConfig get systemMessage => baseConfig.copyWith(
    backgroundColor: Colors.yellow[100],
    textColor: Colors.grey[700],
    showAvatar: false,
  );
}

4. 폼 필드 설정 복제

dart

class FormFieldConfig implements Cloneable<FormFieldConfig> {
  final InputDecoration decoration;
  final TextInputType keyboardType;
  final bool obscureText;
  final String? Function(String?)? validator;
  final int? maxLines;
  
  FormFieldConfig({
    required this.decoration,
    required this.keyboardType,
    this.obscureText = false,
    this.validator,
    this.maxLines = 1,
  });
  
  @override
  FormFieldConfig clone() {
    return FormFieldConfig(
      decoration: decoration,
      keyboardType: keyboardType,
      obscureText: obscureText,
      validator: validator,
      maxLines: maxLines,
    );
  }
}

// 사용법: 회원가입 폼
class FormConfigs {
  static final FormFieldConfig _baseConfig = FormFieldConfig(
    decoration: InputDecoration(
      border: OutlineInputBorder(),
      filled: true,
      fillColor: Colors.grey[50],
    ),
    keyboardType: TextInputType.text,
  );
  
  static FormFieldConfig get email => _baseConfig.clone()
    ..keyboardType = TextInputType.emailAddress
    ..decoration = _baseConfig.decoration.copyWith(
      labelText: 'Email',
      prefixIcon: Icon(Icons.email),
    );
    
  static FormFieldConfig get password => _baseConfig.clone()
    ..obscureText = true
    ..decoration = _baseConfig.decoration.copyWith(
      labelText: 'Password',
      prefixIcon: Icon(Icons.lock),
    );
}

플러터에서 언제 사용하면 좋은가?

  1. 테마/스타일 시스템: 기본 스타일을 만들고 변형된 버전들을 생성

  2. 게임 오브젝트: 같은 타입의 캐릭터/아이템을 대량 생성

  3. 폼 설정: 비슷한 입력 필드들의 설정을 재사용

  4. 설정/구성 객체: 복잡한 설정을 복사해서 일부만 수정

  5. 위젯 빌더: 비슷한 위젯들을 템플릿 기반으로 생성

Last updated