팡세영
Log sey
팡세영
전체 방문자
오늘
어제
  • 분류 전체보기 (74)
    • PS (45)
      • programmers (13)
      • 백준 (29)
    • Android (16)
    • Daily (0)
    • Kotlin (6)
    • Design Pattern (2)
    • Java (1)
    • Flutter (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 해쉬맵
  • 실버
  • 안드로이드
  • flutter
  • 정렬
  • Android
  • 자바
  • ArcitecturePattern
  • 백준
  • 골드
  • TestCode
  • programmers #프로그래머스
  • programmers
  • BFS
  • binding
  • 문자열
  • compose
  • 완전탐색
  • 하단네비게이션바
  • 의존성 주입
  • java
  • CustomView
  • 구현
  • Kotlin
  • 코틀린
  • 프로그래머스
  • mvvm
  • DFS
  • LEVEL2
  • 이분탐색

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
팡세영

Log sey

Design Pattern

컴포지션 패턴 (Composition Pattern)

2025. 6. 9. 16:43

컴포지션 패턴은 상속 대신 여러 객체를 조합해 기능을 구성하는 방식이다. 

"is-a(상속)" 관계보다는 "has-a" (구성) 관계를 통해 객체를 구성하자. 

 

상속 기반 구조의 한계 

class Bird {
	void fly() {
    	System.out.println("I can fly");
    }
}

class Penguin extends Bird {
	// 펭귄은 날 수 없는데도 fly()를 상속 받음
}

 

  • 문제: Penguin은 Bird를 상속받았지만, 실제로는 날 수 없는 동물입니다.
  • 이처럼 상속은 계층 구조가 고정되어 있어 잘못된 기능을 포함시킬 가능성이 있습니다.

컴포지션으로 해결

interface FlyBehavior {
    void fly();
}

class CanFly implements FlyBehavior {
    public void fly() {
        System.out.println("I can fly");
    }
}

class CannotFly implements FlyBehavior {
    public void fly() {
        System.out.println("I can't fly");
    }
}

class Bird {
    public Bird(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    private FlyBehavior flyBehavior;
    
    public void performFly() {
        flyBehavior.fly();
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
}

public class Main {
    public static void main(String[] args) {
        Bird eagle = new Bird(new CanFly());
        Bird penguin = new Bird(new CannotFly());

        eagle.performFly();    // I can fly
        penguin.performFly();  // I can't fly

        penguin.setFlyBehavior(new CanFly());
        penguin.performFly();  // I can fly (이제 날 수 있음!)
    }
}

 


Flutter 예제

CustomTextField

import 'package:flutter/material.dart';

class CustomTextField extends StatelessWidget {
  const CustomTextField({
    super.key,
    required this.label,
    required this.controller,
    this.validator,
    this.obscureText = false,
    this.keyboardType = TextInputType.text,
  });

  final String label;
  final TextEditingController controller;
  final String? Function(String?)? validator;
  final bool obscureText;
  final TextInputType keyboardType;
  
  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      obscureText: obscureText,
      keyboardType: keyboardType,
      validator: validator,
      decoration: InputDecoration(
        labelText: label,
        border: const OutlineInputBorder(),
      ),
    );
  }
}

 

외부에서 UI 구성 요소를 주입 받아서 조합

 

장점

유지보수 용이성 공통 UI 요소를 한 곳에서 수정하면 전체에 반영되어 관리가 편리함
재사용성 다양한 화면에서 같은 UI 요소를 쉽게 재사용할 수 있어 코드 중복 감소
디자인 일관성 확보 디자인 변경 시 모든 화면에 동일하게 반영되므로 UI 일관성이 높아짐
확장성 필요에 따라 새로운 속성만 추가해 기능을 확장할 수 있음
가독성 향상 주요 로직과 UI 컴포넌트를 분리함으로써 코드가 더 명확해지고 구조화됨
단위 테스트 용이 각 구성 요소가 작게 쪼개져 있어 독립적으로 테스트하기 수월함

 

단점

오버 엔지니어링 가능성 간단한 화면에도 공통 컴포넌트를 만들면 오히려 복잡도 증가
상태 전달 어려움 여러 위젯으로 쪼개면 부모-자식 간 상태 공유/전달이 번거로울 수 있음 
초기 러닝커브 증가 위젯이 지나치게 많아지면 프로젝트에 익숙하지 않은 개발자에게는 전체 흐름을 이해하기 어려울 수 있음

 

'Design Pattern' 카테고리의 다른 글

옵저버 패턴 (Observer Pattern)  (1) 2023.12.27
    'Design Pattern' 카테고리의 다른 글
    • 옵저버 패턴 (Observer Pattern)
    팡세영
    팡세영
    Android, CS, PS

    티스토리툴바