oop-inheritance-composition

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OOP Inheritance and Composition

OOP 继承与组合

Master inheritance and composition to build flexible, maintainable object-oriented systems. This skill focuses on understanding when to use inheritance versus composition and how to apply each effectively.
掌握继承与组合,构建灵活、可维护的面向对象系统。本技能重点讲解何时使用继承而非组合,以及如何有效应用这两种方式。

Inheritance Fundamentals

继承基础

Basic Inheritance in Java

Java中的基础继承

java
// Base class with common behavior
public abstract class Vehicle {
    private String brand;
    private String model;
    private int year;
    protected double currentSpeed;

    protected Vehicle(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.currentSpeed = 0.0;
    }

    // Template method pattern
    public final void start() {
        performSafetyCheck();
        startEngine();
        System.out.println(brand + " " + model + " started");
    }

    // Hook method for subclasses
    protected void performSafetyCheck() {
        System.out.println("Performing basic safety check");
    }

    // Abstract method - must be implemented
    protected abstract void startEngine();

    public void accelerate(double speed) {
        currentSpeed += speed;
        System.out.println("Current speed: " + currentSpeed);
    }

    public void brake(double reduction) {
        currentSpeed = Math.max(0, currentSpeed - reduction);
        System.out.println("Current speed: " + currentSpeed);
    }

    // Getters
    public String getBrand() { return brand; }
    public String getModel() { return model; }
    public int getYear() { return year; }
    public double getCurrentSpeed() { return currentSpeed; }
}

// Concrete implementation
public class Car extends Vehicle {
    private int numberOfDoors;
    private boolean isSunroofOpen;

    public Car(String brand, String model, int year, int numberOfDoors) {
        super(brand, model, year);
        this.numberOfDoors = numberOfDoors;
        this.isSunroofOpen = false;
    }

    @Override
    protected void startEngine() {
        System.out.println("Car engine started with ignition");
    }

    @Override
    protected void performSafetyCheck() {
        super.performSafetyCheck();
        System.out.println("Checking doors are closed");
        System.out.println("Checking seatbelts");
    }

    public void openSunroof() {
        if (currentSpeed == 0) {
            isSunroofOpen = true;
            System.out.println("Sunroof opened");
        } else {
            System.out.println("Stop the car before opening sunroof");
        }
    }

    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

// Another concrete implementation
public class Motorcycle extends Vehicle {
    private boolean hasWindshield;

    public Motorcycle(String brand, String model, int year, boolean hasWindshield) {
        super(brand, model, year);
        this.hasWindshield = hasWindshield;
    }

    @Override
    protected void startEngine() {
        System.out.println("Motorcycle engine started with kick/button");
    }

    @Override
    public void accelerate(double speed) {
        // Override to add motorcycle-specific behavior
        if (currentSpeed + speed > 200) {
            System.out.println("Warning: Maximum safe speed exceeded!");
        }
        super.accelerate(speed);
    }

    public boolean hasWindshield() {
        return hasWindshield;
    }
}
java
// Base class with common behavior
public abstract class Vehicle {
    private String brand;
    private String model;
    private int year;
    protected double currentSpeed;

    protected Vehicle(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.currentSpeed = 0.0;
    }

    // Template method pattern
    public final void start() {
        performSafetyCheck();
        startEngine();
        System.out.println(brand + " " + model + " started");
    }

    // Hook method for subclasses
    protected void performSafetyCheck() {
        System.out.println("Performing basic safety check");
    }

    // Abstract method - must be implemented
    protected abstract void startEngine();

    public void accelerate(double speed) {
        currentSpeed += speed;
        System.out.println("Current speed: " + currentSpeed);
    }

    public void brake(double reduction) {
        currentSpeed = Math.max(0, currentSpeed - reduction);
        System.out.println("Current speed: " + currentSpeed);
    }

    // Getters
    public String getBrand() { return brand; }
    public String getModel() { return model; }
    public int getYear() { return year; }
    public double getCurrentSpeed() { return currentSpeed; }
}

// Concrete implementation
public class Car extends Vehicle {
    private int numberOfDoors;
    private boolean isSunroofOpen;

    public Car(String brand, String model, int year, int numberOfDoors) {
        super(brand, model, year);
        this.numberOfDoors = numberOfDoors;
        this.isSunroofOpen = false;
    }

    @Override
    protected void startEngine() {
        System.out.println("Car engine started with ignition");
    }

    @Override
    protected void performSafetyCheck() {
        super.performSafetyCheck();
        System.out.println("Checking doors are closed");
        System.out.println("Checking seatbelts");
    }

    public void openSunroof() {
        if (currentSpeed == 0) {
            isSunroofOpen = true;
            System.out.println("Sunroof opened");
        } else {
            System.out.println("Stop the car before opening sunroof");
        }
    }

    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

// Another concrete implementation
public class Motorcycle extends Vehicle {
    private boolean hasWindshield;

    public Motorcycle(String brand, String model, int year, boolean hasWindshield) {
        super(brand, model, year);
        this.hasWindshield = hasWindshield;
    }

    @Override
    protected void startEngine() {
        System.out.println("Motorcycle engine started with kick/button");
    }

    @Override
    public void accelerate(double speed) {
        // Override to add motorcycle-specific behavior
        if (currentSpeed + speed > 200) {
            System.out.println("Warning: Maximum safe speed exceeded!");
        }
        super.accelerate(speed);
    }

    public boolean hasWindshield() {
        return hasWindshield;
    }
}

Inheritance in Python

Python中的继承

python
from abc import ABC, abstractmethod
from typing import List, Optional
from datetime import datetime

class Employee(ABC):
    """Abstract base class for all employees."""

    def __init__(self, employee_id: str, name: str, email: str, hire_date: datetime):
        self._employee_id = employee_id
        self._name = name
        self._email = email
        self._hire_date = hire_date
        self._is_active = True

    @property
    def employee_id(self) -> str:
        return self._employee_id

    @property
    def name(self) -> str:
        return self._name

    @property
    def email(self) -> str:
        return self._email

    @property
    def hire_date(self) -> datetime:
        return self._hire_date

    @property
    def years_of_service(self) -> int:
        return (datetime.now() - self._hire_date).days // 365

    # Template method
    def process_payroll(self) -> float:
        """Process payroll - template method."""
        if not self._is_active:
            raise ValueError("Cannot process payroll for inactive employee")

        base_pay = self.calculate_pay()
        bonus = self.calculate_bonus()
        deductions = self.calculate_deductions()

        total_pay = base_pay + bonus - deductions
        self.record_payment(total_pay)
        return total_pay

    # Abstract methods - must be implemented by subclasses
    @abstractmethod
    def calculate_pay(self) -> float:
        """Calculate base pay."""
        pass

    # Hook methods with default implementation
    def calculate_bonus(self) -> float:
        """Calculate bonus - can be overridden."""
        return 0.0

    def calculate_deductions(self) -> float:
        """Calculate deductions - can be overridden."""
        return 0.0

    def record_payment(self, amount: float) -> None:
        """Record payment."""
        print(f"Recording payment of ${amount:.2f} for {self._name}")

    def deactivate(self) -> None:
        """Deactivate employee."""
        self._is_active = False


class SalariedEmployee(Employee):
    """Employee paid a fixed salary."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._annual_salary = annual_salary

    def calculate_pay(self) -> float:
        """Calculate monthly salary."""
        return self._annual_salary / 12

    def calculate_bonus(self) -> float:
        """Annual bonus based on years of service."""
        return self._annual_salary * 0.01 * self.years_of_service


class HourlyEmployee(Employee):
    """Employee paid by the hour."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        hourly_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._hourly_rate = hourly_rate
        self._hours_worked = 0.0

    def log_hours(self, hours: float) -> None:
        """Log hours worked this period."""
        if hours < 0:
            raise ValueError("Hours cannot be negative")
        self._hours_worked += hours

    def calculate_pay(self) -> float:
        """Calculate pay based on hours worked."""
        regular_hours = min(self._hours_worked, 40)
        overtime_hours = max(0, self._hours_worked - 40)

        regular_pay = regular_hours * self._hourly_rate
        overtime_pay = overtime_hours * self._hourly_rate * 1.5

        return regular_pay + overtime_pay

    def record_payment(self, amount: float) -> None:
        """Record payment and reset hours."""
        super().record_payment(amount)
        self._hours_worked = 0.0


class CommissionEmployee(SalariedEmployee):
    """Employee with base salary plus commission."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float,
        commission_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date, annual_salary)
        self._commission_rate = commission_rate
        self._sales_this_period = 0.0

    def record_sale(self, amount: float) -> None:
        """Record a sale for commission calculation."""
        if amount <= 0:
            raise ValueError("Sale amount must be positive")
        self._sales_this_period += amount

    def calculate_pay(self) -> float:
        """Calculate base salary plus commission."""
        base = super().calculate_pay()
        commission = self._sales_this_period * self._commission_rate
        return base + commission

    def record_payment(self, amount: float) -> None:
        """Record payment and reset sales."""
        super().record_payment(amount)
        self._sales_this_period = 0.0
python
from abc import ABC, abstractmethod
from typing import List, Optional
from datetime import datetime

class Employee(ABC):
    """Abstract base class for all employees."""

    def __init__(self, employee_id: str, name: str, email: str, hire_date: datetime):
        self._employee_id = employee_id
        self._name = name
        self._email = email
        self._hire_date = hire_date
        self._is_active = True

    @property
    def employee_id(self) -> str:
        return self._employee_id

    @property
    def name(self) -> str:
        return self._name

    @property
    def email(self) -> str:
        return self._email

    @property
    def hire_date(self) -> datetime:
        return self._hire_date

    @property
    def years_of_service(self) -> int:
        return (datetime.now() - self._hire_date).days // 365

    # Template method
    def process_payroll(self) -> float:
        """Process payroll - template method."""
        if not self._is_active:
            raise ValueError("Cannot process payroll for inactive employee")

        base_pay = self.calculate_pay()
        bonus = self.calculate_bonus()
        deductions = self.calculate_deductions()

        total_pay = base_pay + bonus - deductions
        self.record_payment(total_pay)
        return total_pay

    # Abstract methods - must be implemented by subclasses
    @abstractmethod
    def calculate_pay(self) -> float:
        """Calculate base pay."""
        pass

    # Hook methods with default implementation
    def calculate_bonus(self) -> float:
        """Calculate bonus - can be overridden."""
        return 0.0

    def calculate_deductions(self) -> float:
        """Calculate deductions - can be overridden."""
        return 0.0

    def record_payment(self, amount: float) -> None:
        """Record payment."""
        print(f"Recording payment of ${amount:.2f} for {self._name}")

    def deactivate(self) -> None:
        """Deactivate employee."""
        self._is_active = False


class SalariedEmployee(Employee):
    """Employee paid a fixed salary."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._annual_salary = annual_salary

    def calculate_pay(self) -> float:
        """Calculate monthly salary."""
        return self._annual_salary / 12

    def calculate_bonus(self) -> float:
        """Annual bonus based on years of service."""
        return self._annual_salary * 0.01 * self.years_of_service


class HourlyEmployee(Employee):
    """Employee paid by the hour."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        hourly_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._hourly_rate = hourly_rate
        self._hours_worked = 0.0

    def log_hours(self, hours: float) -> None:
        """Log hours worked this period."""
        if hours < 0:
            raise ValueError("Hours cannot be negative")
        self._hours_worked += hours

    def calculate_pay(self) -> float:
        """Calculate pay based on hours worked."""
        regular_hours = min(self._hours_worked, 40)
        overtime_hours = max(0, self._hours_worked - 40)

        regular_pay = regular_hours * self._hourly_rate
        overtime_pay = overtime_hours * self._hourly_rate * 1.5

        return regular_pay + overtime_pay

    def record_payment(self, amount: float) -> None:
        """Record payment and reset hours."""
        super().record_payment(amount)
        self._hours_worked = 0.0


class CommissionEmployee(SalariedEmployee):
    """Employee with base salary plus commission."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float,
        commission_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date, annual_salary)
        self._commission_rate = commission_rate
        self._sales_this_period = 0.0

    def record_sale(self, amount: float) -> None:
        """Record a sale for commission calculation."""
        if amount <= 0:
            raise ValueError("Sale amount must be positive")
        self._sales_this_period += amount

    def calculate_pay(self) -> float:
        """Calculate base salary plus commission."""
        base = super().calculate_pay()
        commission = self._sales_this_period * self._commission_rate
        return base + commission

    def record_payment(self, amount: float) -> None:
        """Record payment and reset sales."""
        super().record_payment(amount)
        self._sales_this_period = 0.0

Inheritance in TypeScript

TypeScript中的继承

typescript
// Abstract base class
abstract class Shape {
  protected readonly id: string;
  protected color: string;

  constructor(color: string) {
    this.id = crypto.randomUUID();
    this.color = color;
  }

  // Abstract methods
  abstract area(): number;
  abstract perimeter(): number;
  abstract draw(): void;

  // Concrete methods
  getColor(): string {
    return this.color;
  }

  setColor(color: string): void {
    this.color = color;
  }

  describe(): string {
    return `${this.constructor.name} (${this.color}): Area = ${this.area().toFixed(2)}, Perimeter = ${this.perimeter().toFixed(2)}`;
  }
}

// Concrete implementations
class Circle extends Shape {
  private radius: number;

  constructor(color: string, radius: number) {
    super(color);
    if (radius <= 0) {
      throw new Error("Radius must be positive");
    }
    this.radius = radius;
  }

  area(): number {
    return Math.PI * this.radius ** 2;
  }

  perimeter(): number {
    return 2 * Math.PI * this.radius;
  }

  draw(): void {
    console.log(`Drawing a ${this.color} circle with radius ${this.radius}`);
  }

  getRadius(): number {
    return this.radius;
  }
}

class Rectangle extends Shape {
  private width: number;
  private height: number;

  constructor(color: string, width: number, height: number) {
    super(color);
    if (width <= 0 || height <= 0) {
      throw new Error("Dimensions must be positive");
    }
    this.width = width;
    this.height = height;
  }

  area(): number {
    return this.width * this.height;
  }

  perimeter(): number {
    return 2 * (this.width + this.height);
  }

  draw(): void {
    console.log(`Drawing a ${this.color} rectangle ${this.width}x${this.height}`);
  }

  isSquare(): boolean {
    return this.width === this.height;
  }
}

class Triangle extends Shape {
  private sideA: number;
  private sideB: number;
  private sideC: number;

  constructor(color: string, sideA: number, sideB: number, sideC: number) {
    super(color);
    if (!this.isValidTriangle(sideA, sideB, sideC)) {
      throw new Error("Invalid triangle dimensions");
    }
    this.sideA = sideA;
    this.sideB = sideB;
    this.sideC = sideC;
  }

  private isValidTriangle(a: number, b: number, c: number): boolean {
    return a + b > c && b + c > a && a + c > b;
  }

  area(): number {
    // Heron's formula
    const s = this.perimeter() / 2;
    return Math.sqrt(s * (s - this.sideA) * (s - this.sideB) * (s - this.sideC));
  }

  perimeter(): number {
    return this.sideA + this.sideB + this.sideC;
  }

  draw(): void {
    console.log(`Drawing a ${this.color} triangle`);
  }
}
typescript
// Abstract base class
abstract class Shape {
  protected readonly id: string;
  protected color: string;

  constructor(color: string) {
    this.id = crypto.randomUUID();
    this.color = color;
  }

  // Abstract methods
  abstract area(): number;
  abstract perimeter(): number;
  abstract draw(): void;

  // Concrete methods
  getColor(): string {
    return this.color;
  }

  setColor(color: string): void {
    this.color = color;
  }

  describe(): string {
    return `${this.constructor.name} (${this.color}): Area = ${this.area().toFixed(2)}, Perimeter = ${this.perimeter().toFixed(2)}`;
  }
}

// Concrete implementations
class Circle extends Shape {
  private radius: number;

  constructor(color: string, radius: number) {
    super(color);
    if (radius <= 0) {
      throw new Error("Radius must be positive");
    }
    this.radius = radius;
  }

  area(): number {
    return Math.PI * this.radius ** 2;
  }

  perimeter(): number {
    return 2 * Math.PI * this.radius;
  }

  draw(): void {
    console.log(`Drawing a ${this.color} circle with radius ${this.radius}`);
  }

  getRadius(): number {
    return this.radius;
  }
}

class Rectangle extends Shape {
  private width: number;
  private height: number;

  constructor(color: string, width: number, height: number) {
    super(color);
    if (width <= 0 || height <= 0) {
      throw new Error("Dimensions must be positive");
    }
    this.width = width;
    this.height = height;
  }

  area(): number {
    return this.width * this.height;
  }

  perimeter(): number {
    return 2 * (this.width + this.height);
  }

  draw(): void {
    console.log(`Drawing a ${this.color} rectangle ${this.width}x${this.height}`);
  }

  isSquare(): boolean {
    return this.width === this.height;
  }
}

class Triangle extends Shape {
  private sideA: number;
  private sideB: number;
  private sideC: number;

  constructor(color: string, sideA: number, sideB: number, sideC: number) {
    super(color);
    if (!this.isValidTriangle(sideA, sideB, sideC)) {
      throw new Error("Invalid triangle dimensions");
    }
    this.sideA = sideA;
    this.sideB = sideB;
    this.sideC = sideC;
  }

  private isValidTriangle(a: number, b: number, c: number): boolean {
    return a + b > c && b + c > a && a + c > b;
  }

  area(): number {
    // Heron's formula
    const s = this.perimeter() / 2;
    return Math.sqrt(s * (s - this.sideA) * (s - this.sideB) * (s - this.sideC));
  }

  perimeter(): number {
    return this.sideA + this.sideB + this.sideC;
  }

  draw(): void {
    console.log(`Drawing a ${this.color} triangle`);
  }
}

Composition Over Inheritance

组合优于继承

Composition in Java

Java中的组合

java
// Component interfaces
interface Engine {
    void start();
    void stop();
    int getHorsepower();
}

interface Transmission {
    void shiftUp();
    void shiftDown();
    String getType();
}

interface GPS {
    void navigate(String destination);
    String getCurrentLocation();
}

// Concrete component implementations
class V6Engine implements Engine {
    private final int horsepower;
    private boolean running;

    public V6Engine(int horsepower) {
        this.horsepower = horsepower;
        this.running = false;
    }

    @Override
    public void start() {
        running = true;
        System.out.println("V6 engine started");
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("V6 engine stopped");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }
}

class ElectricEngine implements Engine {
    private final int horsepower;
    private boolean running;
    private int batteryLevel;

    public ElectricEngine(int horsepower) {
        this.horsepower = horsepower;
        this.batteryLevel = 100;
        this.running = false;
    }

    @Override
    public void start() {
        if (batteryLevel > 0) {
            running = true;
            System.out.println("Electric engine started silently");
        } else {
            System.out.println("Battery depleted!");
        }
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("Electric engine stopped");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }

    public int getBatteryLevel() {
        return batteryLevel;
    }
}

class AutomaticTransmission implements Transmission {
    private int currentGear;

    public AutomaticTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 8) {
            currentGear++;
            System.out.println("Automatically shifted to gear " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("Automatically shifted to gear " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "Automatic";
    }
}

class ManualTransmission implements Transmission {
    private int currentGear;

    public ManualTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 6) {
            currentGear++;
            System.out.println("Manually shifted to gear " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("Manually shifted to gear " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "Manual";
    }
}

// Composed car class
public class ComposedCar {
    private final Engine engine;
    private final Transmission transmission;
    private final GPS gps;  // Optional component
    private final String brand;
    private final String model;

    // Builder for flexible construction
    public static class Builder {
        private Engine engine;
        private Transmission transmission;
        private GPS gps;
        private String brand;
        private String model;

        public Builder brand(String brand) {
            this.brand = brand;
            return this;
        }

        public Builder model(String model) {
            this.model = model;
            return this;
        }

        public Builder engine(Engine engine) {
            this.engine = engine;
            return this;
        }

        public Builder transmission(Transmission transmission) {
            this.transmission = transmission;
            return this;
        }

        public Builder gps(GPS gps) {
            this.gps = gps;
            return this;
        }

        public ComposedCar build() {
            if (engine == null || transmission == null) {
                throw new IllegalStateException("Engine and transmission required");
            }
            return new ComposedCar(this);
        }
    }

    private ComposedCar(Builder builder) {
        this.engine = builder.engine;
        this.transmission = builder.transmission;
        this.gps = builder.gps;
        this.brand = builder.brand;
        this.model = builder.model;
    }

    // Delegate to components
    public void start() {
        engine.start();
        System.out.println(brand + " " + model + " is ready to drive");
    }

    public void stop() {
        engine.stop();
    }

    public void shiftUp() {
        transmission.shiftUp();
    }

    public void shiftDown() {
        transmission.shiftDown();
    }

    public void navigateTo(String destination) {
        if (gps != null) {
            gps.navigate(destination);
        } else {
            System.out.println("GPS not available");
        }
    }

    public String getSpecs() {
        return String.format("%s %s - %d HP %s transmission",
            brand, model, engine.getHorsepower(), transmission.getType());
    }
}

// Usage
ComposedCar sportsCar = new ComposedCar.Builder()
    .brand("Porsche")
    .model("911")
    .engine(new V6Engine(450))
    .transmission(new ManualTransmission())
    .build();

ComposedCar electricCar = new ComposedCar.Builder()
    .brand("Tesla")
    .model("Model 3")
    .engine(new ElectricEngine(283))
    .transmission(new AutomaticTransmission())
    .build();
java
// Component interfaces
interface Engine {
    void start();
    void stop();
    int getHorsepower();
}

interface Transmission {
    void shiftUp();
    void shiftDown();
    String getType();
}

interface GPS {
    void navigate(String destination);
    String getCurrentLocation();
}

// Concrete component implementations
class V6Engine implements Engine {
    private final int horsepower;
    private boolean running;

    public V6Engine(int horsepower) {
        this.horsepower = horsepower;
        this.running = false;
    }

    @Override
    public void start() {
        running = true;
        System.out.println("V6 engine started");
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("V6 engine stopped");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }
}

class ElectricEngine implements Engine {
    private final int horsepower;
    private boolean running;
    private int batteryLevel;

    public ElectricEngine(int horsepower) {
        this.horsepower = horsepower;
        this.batteryLevel = 100;
        this.running = false;
    }

    @Override
    public void start() {
        if (batteryLevel > 0) {
            running = true;
            System.out.println("Electric engine started silently");
        } else {
            System.out.println("Battery depleted!");
        }
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("Electric engine stopped");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }

    public int getBatteryLevel() {
        return batteryLevel;
    }
}

class AutomaticTransmission implements Transmission {
    private int currentGear;

    public AutomaticTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 8) {
            currentGear++;
            System.out.println("Automatically shifted to gear " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("Automatically shifted to gear " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "Automatic";
    }
}

class ManualTransmission implements Transmission {
    private int currentGear;

    public ManualTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 6) {
            currentGear++;
            System.out.println("Manually shifted to gear " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("Manually shifted to gear " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "Manual";
    }
}

// Composed car class
public class ComposedCar {
    private final Engine engine;
    private final Transmission transmission;
    private final GPS gps;  // Optional component
    private final String brand;
    private final String model;

    // Builder for flexible construction
    public static class Builder {
        private Engine engine;
        private Transmission transmission;
        private GPS gps;
        private String brand;
        private String model;

        public Builder brand(String brand) {
            this.brand = brand;
            return this;
        }

        public Builder model(String model) {
            this.model = model;
            return this;
        }

        public Builder engine(Engine engine) {
            this.engine = engine;
            return this;
        }

        public Builder transmission(Transmission transmission) {
            this.transmission = transmission;
            return this;
        }

        public Builder gps(GPS gps) {
            this.gps = gps;
            return this;
        }

        public ComposedCar build() {
            if (engine == null || transmission == null) {
                throw new IllegalStateException("Engine and transmission required");
            }
            return new ComposedCar(this);
        }
    }

    private ComposedCar(Builder builder) {
        this.engine = builder.engine;
        this.transmission = builder.transmission;
        this.gps = builder.gps;
        this.brand = builder.brand;
        this.model = builder.model;
    }

    // Delegate to components
    public void start() {
        engine.start();
        System.out.println(brand + " " + model + " is ready to drive");
    }

    public void stop() {
        engine.stop();
    }

    public void shiftUp() {
        transmission.shiftUp();
    }

    public void shiftDown() {
        transmission.shiftDown();
    }

    public void navigateTo(String destination) {
        if (gps != null) {
            gps.navigate(destination);
        } else {
            System.out.println("GPS not available");
        }
    }

    public String getSpecs() {
        return String.format("%s %s - %d HP %s transmission",
            brand, model, engine.getHorsepower(), transmission.getType());
    }
}

// Usage
ComposedCar sportsCar = new ComposedCar.Builder()
    .brand("Porsche")
    .model("911")
    .engine(new V6Engine(450))
    .transmission(new ManualTransmission())
    .build();

ComposedCar electricCar = new ComposedCar.Builder()
    .brand("Tesla")
    .model("Model 3")
    .engine(new ElectricEngine(283))
    .transmission(new AutomaticTransmission())
    .build();

Composition in Python

Python中的组合

python
from typing import Protocol, List, Optional
from dataclasses import dataclass
python
from typing import Protocol, List, Optional
from dataclasses import dataclass

Component protocols (interfaces)

Component protocols (interfaces)

class Renderer(Protocol): """Protocol for rendering components.""" def render(self, content: str) -> str: ...
class Logger(Protocol): """Protocol for logging components.""" def log(self, message: str, level: str) -> None: ...
class Validator(Protocol): """Protocol for validation components.""" def validate(self, data: dict) -> bool: ... def get_errors(self) -> List[str]: ...
class Renderer(Protocol): """Protocol for rendering components.""" def render(self, content: str) -> str: ...
class Logger(Protocol): """Protocol for logging components.""" def log(self, message: str, level: str) -> None: ...
class Validator(Protocol): """Protocol for validation components.""" def validate(self, data: dict) -> bool: ... def get_errors(self) -> List[str]: ...

Concrete component implementations

Concrete component implementations

class HTMLRenderer: """Renders content as HTML."""
def render(self, content: str) -> str:
    return f"<html><body>{content}</body></html>"
class MarkdownRenderer: """Renders content as Markdown."""
def render(self, content: str) -> str:
    return f"# {content}\n\nRendered as Markdown"
class FileLogger: """Logs messages to a file."""
def __init__(self, filename: str):
    self.filename = filename

def log(self, message: str, level: str) -> None:
    with open(self.filename, 'a') as f:
        f.write(f"[{level}] {message}\n")
class ConsoleLogger: """Logs messages to console."""
def log(self, message: str, level: str) -> None:
    print(f"[{level}] {message}")
class EmailValidator: """Validates email addresses."""
def __init__(self):
    self.errors: List[str] = []

def validate(self, data: dict) -> bool:
    self.errors = []
    email = data.get('email', '')

    if not email:
        self.errors.append("Email is required")
        return False

    if '@' not in email:
        self.errors.append("Email must contain @")
        return False

    if '.' not in email.split('@')[1]:
        self.errors.append("Email must have valid domain")
        return False

    return True

def get_errors(self) -> List[str]:
    return self.errors
class HTMLRenderer: """Renders content as HTML."""
def render(self, content: str) -> str:
    return f"<html><body>{content}</body></html>"
class MarkdownRenderer: """Renders content as Markdown."""
def render(self, content: str) -> str:
    return f"# {content}\n\nRendered as Markdown"
class FileLogger: """Logs messages to a file."""
def __init__(self, filename: str):
    self.filename = filename

def log(self, message: str, level: str) -> None:
    with open(self.filename, 'a') as f:
        f.write(f"[{level}] {message}\n")
class ConsoleLogger: """Logs messages to console."""
def log(self, message: str, level: str) -> None:
    print(f"[{level}] {message}")
class EmailValidator: """Validates email addresses."""
def __init__(self):
    self.errors: List[str] = []

def validate(self, data: dict) -> bool:
    self.errors = []
    email = data.get('email', '')

    if not email:
        self.errors.append("Email is required")
        return False

    if '@' not in email:
        self.errors.append("Email must contain @")
        return False

    if '.' not in email.split('@')[1]:
        self.errors.append("Email must have valid domain")
        return False

    return True

def get_errors(self) -> List[str]:
    return self.errors

Composed class using dependency injection

Composed class using dependency injection

class UserService: """Service composed of various components."""
def __init__(
    self,
    renderer: Renderer,
    logger: Logger,
    validator: Validator
):
    self._renderer = renderer
    self._logger = logger
    self._validator = validator

def create_user(self, user_data: dict) -> Optional[str]:
    """Create user using composed components."""
    self._logger.log(f"Creating user: {user_data.get('email')}", "INFO")

    # Use validator component
    if not self._validator.validate(user_data):
        errors = self._validator.get_errors()
        self._logger.log(f"Validation failed: {errors}", "ERROR")
        return None

    # Process user creation
    user_content = f"User created: {user_data['email']}"

    # Use renderer component
    rendered = self._renderer.render(user_content)
    self._logger.log("User created successfully", "INFO")

    return rendered
class UserService: """Service composed of various components."""
def __init__(
    self,
    renderer: Renderer,
    logger: Logger,
    validator: Validator
):
    self._renderer = renderer
    self._logger = logger
    self._validator = validator

def create_user(self, user_data: dict) -> Optional[str]:
    """Create user using composed components."""
    self._logger.log(f"Creating user: {user_data.get('email')}", "INFO")

    # Use validator component
    if not self._validator.validate(user_data):
        errors = self._validator.get_errors()
        self._logger.log(f"Validation failed: {errors}", "ERROR")
        return None

    # Process user creation
    user_content = f"User created: {user_data['email']}"

    # Use renderer component
    rendered = self._renderer.render(user_content)
    self._logger.log("User created successfully", "INFO")

    return rendered

Component swapping at runtime

Component swapping at runtime

class CompositeLogger: """Logger that delegates to multiple loggers."""
def __init__(self, loggers: List[Logger]):
    self._loggers = loggers

def log(self, message: str, level: str) -> None:
    for logger in self._loggers:
        logger.log(message, level)

def add_logger(self, logger: Logger) -> None:
    self._loggers.append(logger)
class CompositeLogger: """Logger that delegates to multiple loggers."""
def __init__(self, loggers: List[Logger]):
    self._loggers = loggers

def log(self, message: str, level: str) -> None:
    for logger in self._loggers:
        logger.log(message, level)

def add_logger(self, logger: Logger) -> None:
    self._loggers.append(logger)

Usage with different compositions

Usage with different compositions

html_service = UserService( renderer=HTMLRenderer(), logger=ConsoleLogger(), validator=EmailValidator() )
markdown_service = UserService( renderer=MarkdownRenderer(), logger=CompositeLogger([ConsoleLogger(), FileLogger('app.log')]), validator=EmailValidator() )
undefined
html_service = UserService( renderer=HTMLRenderer(), logger=ConsoleLogger(), validator=EmailValidator() )
markdown_service = UserService( renderer=MarkdownRenderer(), logger=CompositeLogger([ConsoleLogger(), FileLogger('app.log')]), validator=EmailValidator() )
undefined

Strategy Pattern with Composition in C

C#中结合组合的策略模式

csharp
// Strategy interfaces
public interface IPaymentStrategy
{
    PaymentResult ProcessPayment(decimal amount);
    bool IsAvailable();
}

public interface IShippingStrategy
{
    decimal CalculateCost(decimal weight, string destination);
    int EstimateDeliveryDays();
}

public interface IDiscountStrategy
{
    decimal ApplyDiscount(decimal originalPrice);
}

// Concrete strategies
public class CreditCardPayment : IPaymentStrategy
{
    private readonly string _cardNumber;
    private readonly string _cvv;

    public CreditCardPayment(string cardNumber, string cvv)
    {
        _cardNumber = cardNumber;
        _cvv = cvv;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        // Credit card processing logic
        Console.WriteLine($"Processing ${amount} via credit card");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class PayPalPayment : IPaymentStrategy
{
    private readonly string _email;

    public PayPalPayment(string email)
    {
        _email = email;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing ${amount} via PayPal");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class StandardShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 2.5m;
    }

    public int EstimateDeliveryDays() => 7;
}

public class ExpressShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 5.0m;
    }

    public int EstimateDeliveryDays() => 2;
}

public class PercentageDiscount : IDiscountStrategy
{
    private readonly decimal _percentage;

    public PercentageDiscount(decimal percentage)
    {
        _percentage = percentage;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return originalPrice * (1 - _percentage / 100);
    }
}

public class FixedAmountDiscount : IDiscountStrategy
{
    private readonly decimal _amount;

    public FixedAmountDiscount(decimal amount)
    {
        _amount = amount;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return Math.Max(0, originalPrice - _amount);
    }
}

// Composed order processor
public class OrderProcessor
{
    private IPaymentStrategy _paymentStrategy;
    private IShippingStrategy _shippingStrategy;
    private IDiscountStrategy? _discountStrategy;

    public OrderProcessor(
        IPaymentStrategy paymentStrategy,
        IShippingStrategy shippingStrategy,
        IDiscountStrategy? discountStrategy = null)
    {
        _paymentStrategy = paymentStrategy ?? throw new ArgumentNullException(nameof(paymentStrategy));
        _shippingStrategy = shippingStrategy ?? throw new ArgumentNullException(nameof(shippingStrategy));
        _discountStrategy = discountStrategy;
    }

    // Strategy can be changed at runtime
    public void SetPaymentStrategy(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetShippingStrategy(IShippingStrategy strategy)
    {
        _shippingStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetDiscountStrategy(IDiscountStrategy? strategy)
    {
        _discountStrategy = strategy;
    }

    public OrderResult ProcessOrder(Order order)
    {
        // Calculate total
        decimal subtotal = order.Items.Sum(item => item.Price * item.Quantity);

        // Apply discount
        decimal total = _discountStrategy?.ApplyDiscount(subtotal) ?? subtotal;

        // Calculate shipping
        decimal shippingCost = _shippingStrategy.CalculateCost(order.TotalWeight, order.Destination);
        total += shippingCost;

        // Process payment
        if (!_paymentStrategy.IsAvailable())
        {
            return OrderResult.Failed("Payment method not available");
        }

        var paymentResult = _paymentStrategy.ProcessPayment(total);
        if (!paymentResult.IsSuccess)
        {
            return OrderResult.Failed("Payment failed");
        }

        return OrderResult.Success(
            order.Id,
            total,
            _shippingStrategy.EstimateDeliveryDays()
        );
    }
}

// Usage
var processor = new OrderProcessor(
    new CreditCardPayment("1234-5678-9012-3456", "123"),
    new StandardShipping(),
    new PercentageDiscount(10)
);

// Change strategy at runtime
processor.SetShippingStrategy(new ExpressShipping());
processor.SetDiscountStrategy(new FixedAmountDiscount(20));
csharp
// Strategy interfaces
public interface IPaymentStrategy
{
    PaymentResult ProcessPayment(decimal amount);
    bool IsAvailable();
}

public interface IShippingStrategy
{
    decimal CalculateCost(decimal weight, string destination);
    int EstimateDeliveryDays();
}

public interface IDiscountStrategy
{
    decimal ApplyDiscount(decimal originalPrice);
}

// Concrete strategies
public class CreditCardPayment : IPaymentStrategy
{
    private readonly string _cardNumber;
    private readonly string _cvv;

    public CreditCardPayment(string cardNumber, string cvv)
    {
        _cardNumber = cardNumber;
        _cvv = cvv;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        // Credit card processing logic
        Console.WriteLine($"Processing ${amount} via credit card");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class PayPalPayment : IPaymentStrategy
{
    private readonly string _email;

    public PayPalPayment(string email)
    {
        _email = email;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing ${amount} via PayPal");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class StandardShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 2.5m;
    }

    public int EstimateDeliveryDays() => 7;
}

public class ExpressShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 5.0m;
    }

    public int EstimateDeliveryDays() => 2;
}

public class PercentageDiscount : IDiscountStrategy
{
    private readonly decimal _percentage;

    public PercentageDiscount(decimal percentage)
    {
        _percentage = percentage;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return originalPrice * (1 - _percentage / 100);
    }
}

public class FixedAmountDiscount : IDiscountStrategy
{
    private readonly decimal _amount;

    public FixedAmountDiscount(decimal amount)
    {
        _amount = amount;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return Math.Max(0, originalPrice - _amount);
    }
}

// Composed order processor
public class OrderProcessor
{
    private IPaymentStrategy _paymentStrategy;
    private IShippingStrategy _shippingStrategy;
    private IDiscountStrategy? _discountStrategy;

    public OrderProcessor(
        IPaymentStrategy paymentStrategy,
        IShippingStrategy shippingStrategy,
        IDiscountStrategy? discountStrategy = null)
    {
        _paymentStrategy = paymentStrategy ?? throw new ArgumentNullException(nameof(paymentStrategy));
        _shippingStrategy = shippingStrategy ?? throw new ArgumentNullException(nameof(shippingStrategy));
        _discountStrategy = discountStrategy;
    }

    // Strategy can be changed at runtime
    public void SetPaymentStrategy(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetShippingStrategy(IShippingStrategy strategy)
    {
        _shippingStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetDiscountStrategy(IDiscountStrategy? strategy)
    {
        _discountStrategy = strategy;
    }

    public OrderResult ProcessOrder(Order order)
    {
        // Calculate total
        decimal subtotal = order.Items.Sum(item => item.Price * item.Quantity);

        // Apply discount
        decimal total = _discountStrategy?.ApplyDiscount(subtotal) ?? subtotal;

        // Calculate shipping
        decimal shippingCost = _shippingStrategy.CalculateCost(order.TotalWeight, order.Destination);
        total += shippingCost;

        // Process payment
        if (!_paymentStrategy.IsAvailable())
        {
            return OrderResult.Failed("Payment method not available");
        }

        var paymentResult = _paymentStrategy.ProcessPayment(total);
        if (!paymentResult.IsSuccess)
        {
            return OrderResult.Failed("Payment failed");
        }

        return OrderResult.Success(
            order.Id,
            total,
            _shippingStrategy.EstimateDeliveryDays()
        );
    }
}

// Usage
var processor = new OrderProcessor(
    new CreditCardPayment("1234-5678-9012-3456", "123"),
    new StandardShipping(),
    new PercentageDiscount(10)
);

// Change strategy at runtime
processor.SetShippingStrategy(new ExpressShipping());
processor.SetDiscountStrategy(new FixedAmountDiscount(20));

Mixin Pattern

混入模式

Mixins in Python

Python中的混入

python
from typing import Any
import json
python
from typing import Any
import json

Mixin classes providing specific functionality

Mixin classes providing specific functionality

class JsonSerializableMixin: """Mixin to add JSON serialization."""
def to_json(self) -> str:
    """Serialize object to JSON."""
    return json.dumps(self.__dict__)

@classmethod
def from_json(cls, json_str: str) -> Any:
    """Deserialize from JSON."""
    data = json.loads(json_str)
    return cls(**data)
class TimestampMixin: """Mixin to add timestamp tracking."""
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.created_at = datetime.now()
    self.updated_at = datetime.now()

def touch(self) -> None:
    """Update the updated_at timestamp."""
    self.updated_at = datetime.now()
class ValidationMixin: """Mixin to add validation capabilities."""
def validate(self) -> bool:
    """Validate object state."""
    errors = self.get_validation_errors()
    return len(errors) == 0

def get_validation_errors(self) -> List[str]:
    """Get list of validation errors."""
    errors = []
    for attr_name, attr_value in self.__dict__.items():
        if attr_value is None and not attr_name.startswith('_'):
            errors.append(f"{attr_name} is required")
    return errors
class AuditMixin: """Mixin to add audit trail."""
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self._changes: List[dict] = []

def record_change(self, field: str, old_value: Any, new_value: Any) -> None:
    """Record a change to the audit trail."""
    self._changes.append({
        'field': field,
        'old_value': old_value,
        'new_value': new_value,
        'timestamp': datetime.now()
    })

def get_audit_trail(self) -> List[dict]:
    """Get the audit trail."""
    return self._changes.copy()
class JsonSerializableMixin: """Mixin to add JSON serialization."""
def to_json(self) -> str:
    """Serialize object to JSON."""
    return json.dumps(self.__dict__)

@classmethod
def from_json(cls, json_str: str) -> Any:
    """Deserialize from JSON."""
    data = json.loads(json_str)
    return cls(**data)
class TimestampMixin: """Mixin to add timestamp tracking."""
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.created_at = datetime.now()
    self.updated_at = datetime.now()

def touch(self) -> None:
    """Update the updated_at timestamp."""
    self.updated_at = datetime.now()
class ValidationMixin: """Mixin to add validation capabilities."""
def validate(self) -> bool:
    """Validate object state."""
    errors = self.get_validation_errors()
    return len(errors) == 0

def get_validation_errors(self) -> List[str]:
    """Get list of validation errors."""
    errors = []
    for attr_name, attr_value in self.__dict__.items():
        if attr_value is None and not attr_name.startswith('_'):
            errors.append(f"{attr_name} is required")
    return errors
class AuditMixin: """Mixin to add audit trail."""
def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self._changes: List[dict] = []

def record_change(self, field: str, old_value: Any, new_value: Any) -> None:
    """Record a change to the audit trail."""
    self._changes.append({
        'field': field,
        'old_value': old_value,
        'new_value': new_value,
        'timestamp': datetime.now()
    })

def get_audit_trail(self) -> List[dict]:
    """Get the audit trail."""
    return self._changes.copy()
// Combining mixins with a base class class User(TimestampMixin, JsonSerializableMixin, ValidationMixin, AuditMixin): """User class with multiple mixed-in behaviors."""
def __init__(self, username: str, email: str, age: int):
    super().__init__()
    self._username = username
    self._email = email
    self._age = age

@property
def username(self) -> str:
    return self._username

@username.setter
def username(self, value: str) -> None:
    old_value = self._username
    self._username = value
    self.touch()
    self.record_change('username', old_value, value)

@property
def email(self) -> str:
    return self._email

@email.setter
def email(self, value: str) -> None:
    old_value = self._email
    self._email = value
    self.touch()
    self.record_change('email', old_value, value)

def get_validation_errors(self) -> List[str]:
    """Override to add specific validation."""
    errors = super().get_validation_errors()

    if len(self._username) < 3:
        errors.append("Username must be at least 3 characters")

    if '@' not in self._email:
        errors.append("Email must be valid")

    if self._age < 18:
        errors.append("User must be at least 18 years old")

    return errors
// Usage user = User("john_doe", "john@example.com", 25) user.username = "jane_doe" print(user.to_json()) print(user.get_audit_trail()) print(user.validate())
undefined

Combining mixins with a base class

接口隔离

Java中的多接口

class User(TimestampMixin, JsonSerializableMixin, ValidationMixin, AuditMixin): """User class with multiple mixed-in behaviors."""
def __init__(self, username: str, email: str, age: int):
    super().__init__()
    self._username = username
    self._email = email
    self._age = age

@property
def username(self) -> str:
    return self._username

@username.setter
def username(self, value: str) -> None:
    old_value = self._username
    self._username = value
    self.touch()
    self.record_change('username', old_value, value)

@property
def email(self) -> str:
    return self._email

@email.setter
def email(self, value: str) -> None:
    old_value = self._email
    self._email = value
    self.touch()
    self.record_change('email', old_value, value)

def get_validation_errors(self) -> List[str]:
    """Override to add specific validation."""
    errors = super().get_validation_errors()

    if len(self._username) < 3:
        errors.append("Username must be at least 3 characters")

    if '@' not in self._email:
        errors.append("Email must be valid")

    if self._age < 18:
        errors.append("User must be at least 18 years old")

    return errors
java
// Segregated interfaces - clients only depend on what they need
interface Readable {
    String read();
}

interface Writable {
    void write(String content);
}

interface Appendable {
    void append(String content);
}

interface Searchable {
    List<String> search(String query);
}

// Read-only document
class ReadOnlyDocument implements Readable {
    private final String content;

    public ReadOnlyDocument(String content) {
        this.content = content;
    }

    @Override
    public String read() {
        return content;
    }
}

// Full-featured document
class Document implements Readable, Writable, Appendable, Searchable {
    private StringBuilder content;

    public Document(String initialContent) {
        this.content = new StringBuilder(initialContent);
    }

    @Override
    public String read() {
        return content.toString();
    }

    @Override
    public void write(String newContent) {
        content = new StringBuilder(newContent);
    }

    @Override
    public void append(String additionalContent) {
        content.append(additionalContent);
    }

    @Override
    public List<String> search(String query) {
        List<String> results = new ArrayList<>();
        String[] lines = content.toString().split("\n");
        for (String line : lines) {
            if (line.contains(query)) {
                results.add(line);
            }
        }
        return results;
    }
}

// Client that only needs reading
class DocumentViewer {
    private final Readable document;

    public DocumentViewer(Readable document) {
        this.document = document;
    }

    public void display() {
        System.out.println(document.read());
    }
}

// Client that needs reading and searching
class DocumentSearcher {
    private final Readable readable;
    private final Searchable searchable;

    public DocumentSearcher(Readable readable, Searchable searchable) {
        this.readable = readable;
        this.searchable = searchable;
    }

    public void findAndDisplay(String query) {
        List<String> results = searchable.search(query);
        results.forEach(System.out::println);
    }
}

Usage

何时使用本技能

user = User("john_doe", "john@example.com", 25) user.username = "jane_doe" print(user.to_json()) print(user.get_audit_trail()) print(user.validate())
undefined
应用继承与组合的场景:
  1. 设计具有共享行为的类层次结构
  2. 建模IS-A关系(继承)
  3. 建模HAS-A关系(组合)
  4. 创建可扩展的框架
  5. 实现模板方法
  6. 构建灵活、可配置的系统
  7. 避免相关类之间的代码重复
  8. 支持运行时行为变更(组合)
  9. 实现策略模式
  10. 创建插件架构
  11. 通过依赖注入构建可测试的代码
  12. 避免过深的继承层次结构
  13. 支持行为的多种实现
  14. 创建可复用组件
  15. 实现接口隔离

Interface Segregation

最佳实践

Multiple Interfaces in Java

java
// Segregated interfaces - clients only depend on what they need
interface Readable {
    String read();
}

interface Writable {
    void write(String content);
}

interface Appendable {
    void append(String content);
}

interface Searchable {
    List<String> search(String query);
}

// Read-only document
class ReadOnlyDocument implements Readable {
    private final String content;

    public ReadOnlyDocument(String content) {
        this.content = content;
    }

    @Override
    public String read() {
        return content;
    }
}

// Full-featured document
class Document implements Readable, Writable, Appendable, Searchable {
    private StringBuilder content;

    public Document(String initialContent) {
        this.content = new StringBuilder(initialContent);
    }

    @Override
    public String read() {
        return content.toString();
    }

    @Override
    public void write(String newContent) {
        content = new StringBuilder(newContent);
    }

    @Override
    public void append(String additionalContent) {
        content.append(additionalContent);
    }

    @Override
    public List<String> search(String query) {
        List<String> results = new ArrayList<>();
        String[] lines = content.toString().split("\n");
        for (String line : lines) {
            if (line.contains(query)) {
                results.add(line);
            }
        }
        return results;
    }
}

// Client that only needs reading
class DocumentViewer {
    private final Readable document;

    public DocumentViewer(Readable document) {
        this.document = document;
    }

    public void display() {
        System.out.println(document.read());
    }
}

// Client that needs reading and searching
class DocumentSearcher {
    private final Readable readable;
    private final Searchable searchable;

    public DocumentSearcher(Readable readable, Searchable searchable) {
        this.readable = readable;
        this.searchable = searchable;
    }

    public void findAndDisplay(String query) {
        List<String> results = searchable.search(query);
        results.forEach(System.out::println);
    }
}
  1. 优先使用组合而非继承以提升灵活性
  2. 仅在存在真实IS-A关系时使用继承
  3. 保持继承层次结构较浅(最多2-3层)
  4. 适当时将基类设为抽象类
  5. 使用接口/协议定义行为契约
  6. 优先使用小型、聚焦的接口而非大型接口
  7. 依赖注入实现可组合设计
  8. 清晰记录模板方法模式
  9. 必要时通过super调用正确重写方法
  10. 使用final/sealed防止进一步继承
  11. 通过小型、单一职责的组件组合行为
  12. 使用策略模式实现运行时行为变更
  13. 避免受保护字段,改用受保护方法
  14. 尽可能使组合对象不可变
  15. 独立测试每个组件

When to Use This Skill

常见陷阱

Apply inheritance and composition when:
  1. Designing class hierarchies with shared behavior
  2. Modeling IS-A relationships (inheritance)
  3. Modeling HAS-A relationships (composition)
  4. Creating extensible frameworks
  5. Implementing template methods
  6. Building flexible, configurable systems
  7. Avoiding code duplication across related classes
  8. Supporting runtime behavior changes (composition)
  9. Implementing the strategy pattern
  10. Creating plugin architectures
  11. Building testable code with dependency injection
  12. Avoiding deep inheritance hierarchies
  13. Supporting multiple implementations of behavior
  14. Creating reusable components
  15. Implementing interface segregation
  1. 创建过深的继承层次结构
  2. 仅为代码复用使用继承
  3. 继承自具体类
  4. 违反里氏替换原则
  5. 创建职责过多的上帝类
  6. 在组合更合适时过度使用继承
  7. 让所有类继承自通用基类
  8. 使用受保护字段而非私有字段
  9. 在构造函数中忘记调用super()
  10. 在组合中创建循环依赖
  11. 未考虑脆弱基类问题
  12. 使用实现继承而非接口继承
  13. 通过继承创建紧耦合
  14. 未在子类中正确重写equals/hashCode
  15. 在基类中混合关注点

Best Practices

资源

  1. Favor composition over inheritance for flexibility
  2. Use inheritance for true IS-A relationships
  3. Keep inheritance hierarchies shallow (2-3 levels max)
  4. Make base classes abstract when appropriate
  5. Use interfaces/protocols for behavior contracts
  6. Prefer small, focused interfaces over large ones
  7. Use dependency injection for composable designs
  8. Document the template method pattern clearly
  9. Override methods properly with super calls when needed
  10. Use final/sealed to prevent further inheritance
  11. Compose behavior from small, single-purpose components
  12. Use the strategy pattern for runtime behavior changes
  13. Avoid protected fields, use protected methods instead
  14. Make composed objects immutable when possible
  15. Test each component independently

Common Pitfalls

  1. Creating deep inheritance hierarchies
  2. Using inheritance for code reuse alone
  3. Inheriting from concrete classes
  4. Breaking Liskov Substitution Principle
  5. Creating God classes with too many responsibilities
  6. Overusing inheritance when composition would work better
  7. Making everything inherit from a common base class
  8. Using protected fields instead of private
  9. Forgetting to call super() in constructors
  10. Creating circular dependencies in composition
  11. Not considering the fragile base class problem
  12. Using implementation inheritance over interface inheritance
  13. Creating tight coupling through inheritance
  14. Not properly overriding equals/hashCode in subclasses
  15. Mixing concerns in base classes

Resources