Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Composition (Hợp thành) trong C#

Composition (Hợp thành) là mối quan hệ "has-a" mạnh (strong ownership): đối tượng cha (parent) sở hữu đối tượng con (child), và vòng đời của child phụ thuộc vào parent. Khi parent bị hủy, child cũng bị hủy.

Khác với Aggregation (Tổng hợp) - quan hệ "has-a" yếu: child có thể tồn tại độc lập, được share giữa nhiều parent.

Ví dụ: Xe hơi và Động cơ (Composition)

using System;

public class Engine
{
    public int HorsePower { get; }
    public Engine(int hp) { HorsePower = hp; Console.WriteLine("Engine created"); }
    ~Engine() { Console.WriteLine("Engine destroyed"); } // Finalizer demo
}

public class Car
{
    // Composition: Car SỞ HỮU Engine (private field, khởi tạo trong constructor)
    private readonly Engine engine;
    
    public Car(int hp)
    {
        engine = new Engine(hp); // Tạo engine khi Car tạo
        Console.WriteLine("Car created");
    }
    
    public void Start() => Console.WriteLine($"Car started with {engine.HorsePower}HP engine");
    
    ~Car() { Console.WriteLine("Car destroyed"); }
}

class Program
{
    static void Main()
    {
        Console.WriteLine("--- Tạo Car ---");
        Car myCar = new Car(200);
        myCar.Start();
        
        Console.WriteLine("\n--- Car ra khỏi scope ---");
        // myCar bị GC collect -> Engine cũng bị collect cùng lúc
    }
}

Kết quả (thứ tự có thể khác do GC non-deterministic)

--- Tạo Car ---
Engine created
Car created
Car started with 200HP engine

--- Car ra khỏi scope ---
Car destroyed
Engine destroyed

Đặc điểm Composition

Đặc điểmCompositionAggregation
Mối quan hệ"Part-of" (Bộ phận của)"Has-a" (Có)
Vòng đờiChild chết khi Parent chếtChild sống độc lập
Sở hữuĐộc quyền (Exclusive)Chia sẻ (Shared)
UMLHình thoi đậm (●──◇)Hình thoi rỗng (○──◇)
Ví dụCar-Engine, House-Room, Order-OrderItemCar-Driver, Student-Course, Library-Book

Implementation Patterns

1. Composition thuần túy (Private field, khởi tạo trong ctor)

public class Car
{
    private readonly Engine engine = new Engine(200); // Inline init
    // hoặc trong constructor
}

2. Composition với Interface (Loose coupling)

public interface IEngine { void Start(); }
public class V8Engine : IEngine { public void Start() => ... }
public class ElectricEngine : IEngine { public void Start() => ... }

public class Car
{
    private readonly IEngine engine; // Dependency Injection
    public Car(IEngine engine) => this.engine = engine;
}

3. Composite Pattern (Cây đối tượng)

public interface IComponent { void Display(int depth); }

public class Leaf : IComponent { ... }
public class Composite : IComponent 
{
    private List children = new();
    public void Add(IComponent c) => children.Add(c);
    public void Display(int depth) { ... foreach child.Display(depth+1) }
}

Ưu điểm Composition

  • Encapsulation: Che giấu implementation detail.
  • Flexibility: Thay đổi behavior tại runtime (DI).
  • Single Responsibility: Mỗi class một trách nhiệm.
  • Testability: Dễ mock dependency.
  • Tránh kế thừa sâu: "Favor composition over inheritance" (GoF).