|
1 | 1 | /** |
2 | 2 | * @file composition_over_inheritance.cpp |
3 | | - * @author Xuhua Huang |
4 | | - * @brief Inheritance establishes an IS-A relaHonship |
5 | | - * Composition/aggregation establish a HAS-A relaHonship – this can often be preferable |
6 | | - * |
7 | | - * Aggregation |
8 | | - * An object comprised of other objects uses those objects |
9 | | - * Those objects exist outside of the object |
10 | | - * When the object is destroyed, the objects that comprise it remain |
11 | | - * |
12 | | - * @version 0.1 |
13 | | - * @date 2026-04-09 |
14 | | - * |
15 | | - * @copyright Copyright (c) 2026 |
| 3 | + * @brief Demonstration of composition over inheritance using runtime strategies |
16 | 4 | * |
| 5 | + * Key ideas: |
| 6 | + * - Prefer HAS-A over IS-A |
| 7 | + * - Compose behavior dynamically |
| 8 | + * - Keep components orthogonal and swappable |
17 | 9 | */ |
18 | 10 |
|
19 | 11 | #include <iostream> |
20 | 12 | #include <memory> |
21 | | -// #include <string> |
| 13 | +#include <vector> |
| 14 | + |
| 15 | +namespace experimental { |
| 16 | +template <typename MovementPolicy, typename PowerPolicy> |
| 17 | +class vehicle_t; |
| 18 | +} |
22 | 19 |
|
23 | | -class IMovement { |
| 20 | +class movement_t { |
24 | 21 | public: |
25 | | - virtual ~IMovement() = default; |
26 | | - virtual void move() const = 0; |
| 22 | + virtual ~movement_t() = default; |
| 23 | + virtual void move() const = 0; |
| 24 | + virtual const char* describe() const = 0; |
27 | 25 | }; |
28 | 26 |
|
29 | | -class IPowerSource { |
| 27 | +class power_source_t { |
30 | 28 | public: |
31 | | - virtual ~IPowerSource() = default; |
32 | | - virtual void supply_power() const = 0; |
| 29 | + virtual ~power_source_t() = default; |
| 30 | + virtual void supply_power() const = 0; |
| 31 | + virtual const char* describe() const = 0; |
33 | 32 | }; |
34 | 33 |
|
35 | | -class WheelMovement : public IMovement { |
| 34 | +class wheel_movement_t : public movement_t { |
36 | 35 | public: |
37 | 36 | void move() const override { std::cout << "Moving on wheels\n"; } |
| 37 | + |
| 38 | + const char* describe() const override { return "Wheel-based movement"; } |
38 | 39 | }; |
39 | 40 |
|
40 | | -class FlyingMovement : public IMovement { |
| 41 | +class flying_movement_t : public movement_t { |
41 | 42 | public: |
42 | 43 | void move() const override { std::cout << "Flying in the air\n"; } |
| 44 | + |
| 45 | + const char* describe() const override { return "Aerial movement"; } |
43 | 46 | }; |
44 | 47 |
|
45 | | -class GasEngine : public IPowerSource { |
| 48 | +class gas_engine_t : public power_source_t { |
46 | 49 | public: |
47 | 50 | void supply_power() const override { std::cout << "Supplying power from gas engine\n"; } |
| 51 | + |
| 52 | + const char* describe() const override { return "Gas engine"; } |
48 | 53 | }; |
49 | 54 |
|
50 | | -class ElectricBattery : public IPowerSource { |
| 55 | +class electric_battery_t : public power_source_t { |
51 | 56 | public: |
52 | 57 | void supply_power() const override { std::cout << "Supplying power from battery\n"; } |
| 58 | + |
| 59 | + const char* describe() const override { return "Electric battery"; } |
| 60 | +}; |
| 61 | + |
| 62 | +class solar_panel_t : public power_source_t { |
| 63 | +public: |
| 64 | + void supply_power() const override { std::cout << "Supplying power from solar energy\n"; } |
| 65 | + |
| 66 | + const char* describe() const override { return "Solar panel"; } |
| 67 | +}; |
| 68 | + |
| 69 | +// Composite power source (aggregation of multiple sources) |
| 70 | +class hybrid_power_t : public power_source_t { |
| 71 | +public: |
| 72 | + void add_source(std::unique_ptr<power_source_t> source) { sources.push_back(std::move(source)); } |
| 73 | + |
| 74 | + void supply_power() const override { |
| 75 | + std::cout << "Hybrid power system engaged:\n"; |
| 76 | + for (const auto& src : sources) { |
| 77 | + src->supply_power(); |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + const char* describe() const override { return "Hybrid power system"; } |
| 82 | + |
| 83 | +private: |
| 84 | + std::vector<std::unique_ptr<power_source_t>> sources; |
53 | 85 | }; |
54 | 86 |
|
55 | | -class Vehicle { |
| 87 | +class vehicle_t { |
56 | 88 | public: |
57 | | - Vehicle(std::unique_ptr<IMovement> movement, std::unique_ptr<IPowerSource> power_source) |
| 89 | + vehicle_t(std::unique_ptr<movement_t> movement, std::unique_ptr<power_source_t> power_source) |
58 | 90 | : movement(std::move(movement)) |
59 | 91 | , power_source(std::move(power_source)) {} |
60 | 92 |
|
61 | 93 | void operate() const { |
| 94 | + std::cout << "[Vehicle Start]\n"; |
| 95 | + std::cout << "Movement: " << movement->describe() << "\n"; |
| 96 | + std::cout << "Power: " << power_source->describe() << "\n"; |
| 97 | + |
62 | 98 | power_source->supply_power(); |
63 | 99 | movement->move(); |
| 100 | + |
| 101 | + std::cout << "[Vehicle End]\n\n"; |
64 | 102 | } |
65 | 103 |
|
66 | 104 | private: |
67 | | - std::unique_ptr<IMovement> movement; |
68 | | - std::unique_ptr<IPowerSource> power_source; |
| 105 | + std::unique_ptr<movement_t> movement; |
| 106 | + std::unique_ptr<power_source_t> power_source; |
69 | 107 | }; |
70 | 108 |
|
71 | 109 | int main() { |
72 | | - // Traditional car |
73 | | - Vehicle car(std::make_unique<WheelMovement>(), std::make_unique<GasEngine>()); |
| 110 | + vehicle_t car(std::make_unique<wheel_movement_t>(), std::make_unique<gas_engine_t>()); |
| 111 | + |
| 112 | + vehicle_t ev(std::make_unique<wheel_movement_t>(), std::make_unique<electric_battery_t>()); |
74 | 113 |
|
75 | | - // Electric car |
76 | | - Vehicle ev(std::make_unique<WheelMovement>(), std::make_unique<ElectricBattery>()); |
| 114 | + vehicle_t drone(std::make_unique<flying_movement_t>(), std::make_unique<electric_battery_t>()); |
77 | 115 |
|
78 | | - // Futuristic flying electric vehicle |
79 | | - Vehicle drone(std::make_unique<FlyingMovement>(), std::make_unique<ElectricBattery>()); |
| 116 | + // Hybrid example: battery + solar |
| 117 | + auto hybrid_power = std::make_unique<hybrid_power_t>(); |
| 118 | + hybrid_power->add_source(std::make_unique<electric_battery_t>()); |
| 119 | + hybrid_power->add_source(std::make_unique<solar_panel_t>()); |
| 120 | + |
| 121 | + vehicle_t futuristic_vehicle(std::make_unique<flying_movement_t>(), std::move(hybrid_power)); |
80 | 122 |
|
81 | 123 | car.operate(); |
82 | 124 | ev.operate(); |
83 | 125 | drone.operate(); |
| 126 | + futuristic_vehicle.operate(); |
84 | 127 | } |
85 | | - |
86 | | -class SolarPanel : public IPowerSource { |
87 | | -public: |
88 | | - void supply_power() const override { std::cout << "Supplying power from solar energy\n"; } |
89 | | -}; |
|
0 commit comments