Key Concepts
Humble Object Pattern:
Presenter:
Code Example: Presenter + View
#include
#include
// Model (Business Data)
struct Order {
std::string id;
double amount;
};
// View Interface (Humble Object)
class OrderView {
public:
virtual void display(const std::string& formattedData) = 0;
virtual ~OrderView() = default;
};
// Presenter (Converts Model to View-friendly format)
class OrderPresenter {
public:
explicit OrderPresenter(OrderView& view) : view(view) {}
void present(const Order& order) {
std::string formatted = "Order ID: " + order.id + ", Amount: $" + std::to_string(order.amount);
view.display(formatted);
}
private:
OrderView& view;
};
// Concrete View Implementation (Console)
class ConsoleOrderView : public OrderView {
public:
void display(const std::string& formattedData) override {
std::cout << "Displaying Order: " << formattedData << std::endl;
}
};
// Test Case
int main() {
ConsoleOrderView view;
OrderPresenter presenter(view);
Order order{"12345", 99.99};
presenter.present(order); // Output: "Displaying Order: Order ID: 12345, Amount: $99.99"
return 0;
}
Explanation
ConsoleOrderView
has no business logic; it only displays formatted data.OrderPresenter
converts Order
to a string and delegates display to the view.OrderPresenter
, while ConsoleOrderView
is trivially simple.Key Concepts
Partial Boundaries:
Use Cases:
Code Example: Facade Pattern (Partial Boundary)
#include
#include
// Subsystem: Payment Processing
class PaymentProcessor {
public:
virtual void processPayment(double amount) = 0;
virtual ~PaymentProcessor() = default;
};
// Partial Boundary: Facade for Payment + Logistics (incomplete)
class OrderFacade {
public:
explicit OrderFacade(std::unique_ptr<PaymentProcessor> processor)
: paymentProcessor(std::move(processor)) {}
void executeOrder(double amount) {
paymentProcessor->processPayment(amount);
// Logistics not yet implemented (partial boundary)
std::cout << "Logistics pending..." << std::endl;
}
private:
std::unique_ptr<PaymentProcessor> paymentProcessor;
};
// Concrete Payment Processor
class PayPalProcessor : public PaymentProcessor {
public:
void processPayment(double amount) override {
std::cout << "Processing $" << amount << " via PayPal." << std::endl;
}
};
// Test Case
int main() {
auto processor = std::make_unique<PayPalProcessor>();
OrderFacade facade(std::move(processor));
facade.executeOrder(150.0); // Output: "Processing $150 via PayPal. Logistics pending..."
return 0;
}
Explanation
OrderFacade
integrates payment processing but defers logistics (a placeholder).Testing & Compilation
g++ -std=c++17 -o example example.cpp
(adjust filenames as needed).Summary
Code Snippet:
// Humble Object: Simple View
class ConsoleView {
void display(String data) {
System.out.println(data);
}
}
Code Snippet:
# Presenter converts data for View
class ReportPresenter:
def format_report(self, report_data):
return f"Report: {report_data['title']} (${report_data['amount']})"
Code Snippet:
// Facade as a partial boundary
public class OrderFacade {
private OrderService _service = new OrderService();
public void ProcessOrder(Order order) {
_service.Validate(order);
_service.Save(order);
}
}
Code Snippet:
// Testable Presenter with mocked dependencies
@Test
void testReportPresenter() {
var presenter = new ReportPresenter();
String result = presenter.formatReport(new ReportData("Q1", 5000));
assertEquals("Report: Q1 ($5000)", result);
}
Code Snippet:
# Facade with hidden dependency on PaymentService
class PaymentFacade:
def __init__(self):
self._payment_service = PaymentService()
def process(self, amount):
self._payment_service.charge(amount)
Code Snippet:
// One-dimensional boundary with direct dependency
class OrderProcessor {
private ShippingService shippingService = new FedExShippingService();
void process(Order order) {
shippingService.ship(order);
}
}
B, C, D
B, D
B, C
B, D
A, B, D
A, D
B, D
B
B, D
A, C, D
interface DataExporter {
String export(String data);
}
class CSVExporter implements DataExporter {
public String export(String data) {
return "CSV: " + data; // Simple formatting
}
}
class ReportGenerator {
private DataExporter exporter;
public ReportGenerator(DataExporter exporter) {
this.exporter = exporter;
}
public String generateReport(String rawData) {
return exporter.export(rawData.toUpperCase());
}
}
class InventoryService:
def check_stock(self, product_id):
return 100 # Simulated stock check
class OrderFacade:
def __init__(self):
self.inventory = InventoryService()
def place_order(self, product_id, quantity):
if self.inventory.check_stock(product_id) >= quantity:
return "Order placed"
else:
return "Insufficient stock"
public interface IShippingService {
void Ship(Order order);
}
public class FedExShipping : IShippingService {
public void Ship(Order order) {
Console.WriteLine($"Shipping via FedEx: {order.Id}");
}
}
public class OrderProcessor {
private IShippingService shipper;
public OrderProcessor(IShippingService shipper) {
this.shipper = shipper;
}
public void Process(Order order) {
shipper.Ship(order);
}
}