ai

Composition OOP คือ — หลักการ Composition over

Composition OOP คือ — หลักการ Composition over

Composition OOP

Composition OOP คือ — หลักการ Composition over

Composition OOP Has-a Relationship Composition over Inheritance Dependency Injection Design Patterns Loose Coupling Flexibility Runtime Behavior Strategy Decorator

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน Svelte 5 Runes High Availability HA Setup

ConceptRelationshipCouplingFlexibilityเหมาะกับ
InheritanceIs-aTightต่ำTrue Hierarchy
CompositionHas-aLooseสูงทั่วไป
AggregationHas-a (weak)LooseสูงOptional Parts
InterfaceCan-doVery LooseสูงมากContract
MixinMixed-inปานกลางปานกลางShared Behavior

Composition vs Inheritance

# === Composition vs Inheritance ===



# BAD: Deep Inheritance Hierarchy

# class Animal:

#     def eat(self): ...

#

# class Mammal(Animal):

#     def breathe(self): ...

#

# class Dog(Mammal):

#     def bark(self): ...

#

# class GuideDog(Dog):

#     def guide(self): ...

#

# Problem: GuideDog สืบทอด 4 ชั้น เปลี่ยน Animal กระทบทุก Class



# GOOD: Composition

from abc import ABC, abstractmethod

from dataclasses import dataclass, field

from typing import Protocol



# Define Behaviors as Protocols (Interfaces)

class Movable(Protocol):

    def move(self) -> str: ...



class Soundable(Protocol):

    def make_sound(self) -> str: ...



class Trainable(Protocol):

    def perform_task(self, task: str) -> str: ...



# Implement Behaviors as separate classes

class WalkBehavior:

    def move(self) -> str:

        return "Walking on 4 legs"



class FlyBehavior:

    def move(self) -> str:

        return "Flying with wings"



class SwimBehavior:

    def move(self) -> str:

        return "Swimming with fins"



class BarkSound:

    def make_sound(self) -> str:

        return "Woof!"



class MeowSound:

    def make_sound(self) -> str:

        return "Meow!"



class GuideTraining:

    def perform_task(self, task: str) -> str:

        return f"Guiding: {task}"



class SearchTraining:

    def perform_task(self, task: str) -> str:

        return f"Searching for: {task}"



# Compose behaviors into Animal

@dataclass

class Animal:

    name: str

    movement: Movable

    sound: Soundable

    training: Trainable = None



    def describe(self):

        desc = f"{self.name}: {self.movement.move()} | {self.sound.make_sound()}"

        if self.training:

            desc += f" | Can: {self.training.perform_task('demo')}"

        return desc



# Create animals with different compositions

dog = Animal("Dog", WalkBehavior(), BarkSound())

guide_dog = Animal("Guide Dog", WalkBehavior(), BarkSound(), GuideTraining())

search_dog = Animal("Search Dog", WalkBehavior(), BarkSound(), SearchTraining())

cat = Animal("Cat", WalkBehavior(), MeowSound())



animals = [dog, guide_dog, search_dog, cat]

print("=== Composition Example ===")

for a in animals:

    print(f"  {a.describe()}")



# Runtime behavior change!

print("\n  Dog learns to swim:")

dog.movement = SwimBehavior()

print(f"  {dog.describe()}")

Design Patterns

Composition OOP คือ — หลักการ Composition over
# === Strategy Pattern (Composition) ===



class PaymentStrategy(Protocol):

    def pay(self, amount: float) -> str: ...



class CreditCardPayment:

    def __init__(self, card_number: str):

        self.card = card_number[-4:]

    def pay(self, amount: float) -> str:

        return f"Paid  with Credit Card ****{self.card}"



class PayPalPayment:

    def __init__(self, email: str):

        self.email = email

    def pay(self, amount: float) -> str:

        return f"Paid  via PayPal ({self.email})"



class CryptoPayment:

    def __init__(self, wallet: str):

        self.wallet = wallet[:8]

    def pay(self, amount: float) -> str:

        return f"Paid  with Crypto ({self.wallet}...)"



@dataclass

class ShoppingCart:

    items: list = field(default_factory=list)

    payment: PaymentStrategy = None



    def add_item(self, name: str, price: float):

        self.items.append({"name": name, "price": price})



    def total(self) -> float:

        return sum(item["price"] for item in self.items)



    def checkout(self) -> str:

        if not self.payment:

            return "Error: No payment method set"

        return self.payment.pay(self.total())



cart = ShoppingCart()

cart.add_item("Laptop", 999.99)

cart.add_item("Mouse", 29.99)



# Strategy: เปลี่ยน Payment Method ตอน Runtime

cart.payment = CreditCardPayment("4111111111111234")

print(f"\n=== Strategy Pattern ===")

print(f"  {cart.checkout()}")



cart.payment = PayPalPayment("user@example.com")

print(f"  {cart.checkout()}")



cart.payment = CryptoPayment("0x1234567890abcdef")

print(f"  {cart.checkout()}")



# === Decorator Pattern (Composition) ===

class Logger:

    def __init__(self, wrapped):

        self._wrapped = wrapped

    def pay(self, amount: float) -> str:

        print(f"  [LOG] Processing payment of ")

        result = self._wrapped.pay(amount)

        print(f"  [LOG] Payment result: {result}")

        return result



print(f"\n=== Decorator Pattern ===")

logged_payment = Logger(CreditCardPayment("9876543210001234"))

logged_payment.pay(1029.98)

Dependency Injection

# === Dependency Injection with Composition ===



# Database Repository (Interface)

class UserRepository(Protocol):

    def find_by_id(self, user_id: int) -> dict: ...

    def save(self, user: dict) -> bool: ...



# Concrete Implementations

class PostgresUserRepo:

    def find_by_id(self, user_id: int) -> dict:

        return {"id": user_id, "name": "John", "source": "PostgreSQL"}

    def save(self, user: dict) -> bool:

        return True



class MongoUserRepo:

    def find_by_id(self, user_id: int) -> dict:

        return {"id": user_id, "name": "John", "source": "MongoDB"}

    def save(self, user: dict) -> bool:

        return True



class InMemoryUserRepo:

    """For testing"""

    def __init__(self):

        self.users = {}

    def find_by_id(self, user_id: int) -> dict:

        return self.users.get(user_id, {})

    def save(self, user: dict) -> bool:

        self.users[user["id"]] = user

        return True



# Service uses Composition + DI

@dataclass

class UserService:

    repo: UserRepository  # Injected dependency



    def get_user(self, user_id: int) -> dict:

        return self.repo.find_by_id(user_id)



    def update_user(self, user_id: int, name: str) -> bool:

        user = self.repo.find_by_id(user_id)

        user["name"] = name

        return self.repo.save(user)



# Production: ใช้ Postgres

prod_service = UserService(repo=PostgresUserRepo())

print(f"\n=== Dependency Injection ===")

print(f"  Production: {prod_service.get_user(1)}")



# Testing: ใช้ InMemory

test_repo = InMemoryUserRepo()

test_repo.save({"id": 1, "name": "Test User"})

test_service = UserService(repo=test_repo)

print(f"  Testing: {test_service.get_user(1)}")



# Switch to Mongo: เปลี่ยน Implementation ไม่ต้องแก้ Service

mongo_service = UserService(repo=MongoUserRepo())

print(f"  MongoDB: {mongo_service.get_user(1)}")



# Benefits Summary

benefits = {

    "Loose Coupling": "Service ไม่ผูกกับ Database ใดๆ",

    "Testability": "Mock/InMemory Repository สำหรับ Test",

    "Flexibility": "เปลี่ยน Database ไม่ต้องแก้ Business Logic",

    "Single Responsibility": "แต่ละ Class ทำหน้าที่เดียว",

    "Open/Closed": "เพิ่ม Implementation ใหม่ไม่ต้องแก้ Code เดิม",

}



print(f"\n  Composition Benefits:")

for k, v in benefits.items():

    print(f"    [{k}]: {v}")

เคล็ดลับ

  • Favor Composition: เลือก Composition ก่อน ใช้ Inheritance เมื่อจำเป็นจริงๆ
  • Protocol: ใช้ Protocol/Interface กำหนด Contract
  • DI: Inject Dependencies ผ่าน Constructor
  • Small Classes: สร้าง Class เล็กๆ ทำหน้าที่เดียว แล้วรวมกัน
  • Test: Composition ทำให้ Mock ง่าย Test ง่าย

Composition ใน OOP คืออะไร

สร้าง Object รวม Object อื่น Has-a Relationship แทน Inheritance ยืดหยุ่น เปลี่ยน Runtime Loose Coupling Test ง่าย Mock ง่าย

แนะนำเพิ่มเติม — XM Signal

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง Prometheus PromQL Observability Stack

เนื้อหาเกี่ยวข้อง — ดูเพิ่มเติมเรื่อง Prometheus PromQL DevOps Culture

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง