#include <iostream>
#include <string>
#include <memory>
class ReimbursementRequest {
public:
ReimbursementRequest(double amount, const std::string& description)
: amount_(amount), description_(description) {}
double getAmount() const { return amount_; }
std::string getDescription() const { return description_; }
private:
double amount_;
std::string description_;
};
class Approver {
public:
virtual ~Approver() = default;
Approver* setNext(Approver* next) {
next_ = next;
return next;
}
void handleRequest(const ReimbursementRequest& request) {
if (canApprove(request)) {
approve(request);
} else if (next_) {
std::cout << " -> Forwarding to next approver..." << std::endl;
next_->handleRequest(request);
} else {
std::cout << " -> No one can handle this request: "
<< request.getDescription() << " ($"
<< request.getAmount() << ")" << std::endl;
}
}
protected:
virtual bool canApprove(const ReimbursementRequest& request) = 0;
virtual void approve(const ReimbursementRequest& request) = 0;
private:
Approver* next_ = nullptr;
};
class Manager : public Approver {
protected:
bool canApprove(const ReimbursementRequest& request) override {
return request.getAmount() <= 1000;
}
void approve(const ReimbursementRequest& request) override {
std::cout << "Manager approved: " << request.getDescription()
<< " ($" << request.getAmount() << ")" << std::endl;
}
};
class Director : public Approver {
protected:
bool canApprove(const ReimbursementRequest& request) override {
return request.getAmount() <= 5000;
}
void approve(const ReimbursementRequest& request) override {
std::cout << "Director approved: " << request.getDescription()
<< " ($" << request.getAmount() << ")" << std::endl;
}
};
class CEO : public Approver {
protected:
bool canApprove(const ReimbursementRequest& request) override {
return true;
}
void approve(const ReimbursementRequest& request) override {
std::cout << "CEO approved: " << request.getDescription()
<< " ($" << request.getAmount() << ")" << std::endl;
}
};
int main() {
Manager manager;
Director director;
CEO ceo;
manager.setNext(&director)->setNext(&ceo);
std::cout << "=== Testing complete chain (Manager -> Director -> CEO) ===" << std::endl;
ReimbursementRequest req1(800, "Office supplies");
ReimbursementRequest req2(3000, "Team building event");
ReimbursementRequest req3(10000, "New server hardware");
manager.handleRequest(req1);
manager.handleRequest(req2);
manager.handleRequest(req3);
std::cout << "\n=== Testing incomplete chain (Director -> CEO only, Manager missing) ===" << std::endl;
Director director2;
CEO ceo2;
director2.setNext(&ceo2);
director2.handleRequest(req1);
director2.handleRequest(req3);
std::cout << "\n=== Testing chain with no handler for high amount (Manager only) ===" << std::endl;
Manager managerOnly;
managerOnly.handleRequest(req1);
managerOnly.handleRequest(req3);
return 0;
}