#include <iostream>
#include <memory>
#include <string>
class Document;
class DraftState;
class ModerationState;
class PublishedState;
class State {
public:
virtual ~State() = default;
virtual std::string name() const = 0;
virtual void edit(Document& doc) {
std::cout << "Current state (" << name() << ") does not allow editing.\n";
}
virtual void submitForReview(Document& doc) {
std::cout << "Current state (" << name() << ") does not allow submitting for review.\n";
}
virtual void approve(Document& doc) {
std::cout << "Current state (" << name() << ") does not allow approval.\n";
}
virtual void reject(Document& doc) {
std::cout << "Current state (" << name() << ") does not allow rejection.\n";
}
virtual void publish(Document& doc) {
std::cout << "Current state (" << name() << ") does not allow direct publishing.\n";
}
};
class Document {
std::unique_ptr<State> state;
std::string content;
public:
explicit Document(std::unique_ptr<State> initialState)
: state(std::move(initialState)) {}
void setState(std::unique_ptr<State> newState) {
state = std::move(newState);
}
void edit() { state->edit(*this); }
void submitForReview() { state->submitForReview(*this); }
void approve() { state->approve(*this); }
void reject() { state->reject(*this); }
void publish() { state->publish(*this); }
void setContent(const std::string& c) { content = c; }
const std::string& getContent() const { return content; }
std::string getStateName() const { return state->name(); }
};
class DraftState : public State {
public:
std::string name() const override { return "Draft"; }
void edit(Document& doc) override {
std::cout << "Editing document...\n";
doc.setContent("Document content (draft version)");
}
void submitForReview(Document& doc) override;
void publish(Document& doc) override {
std::cout << "Draft cannot be published directly. Submit for review first.\n";
}
};
class ModerationState : public State {
public:
std::string name() const override { return "Under Review"; }
void edit(Document& doc) override {
std::cout << "Cannot edit document while under review.\n";
}
void approve(Document& doc) override;
void reject(Document& doc) override;
};
class PublishedState : public State {
public:
std::string name() const override { return "Published"; }
void edit(Document& doc) override {
std::cout << "Published documents cannot be edited.\n";
}
void submitForReview(Document& doc) override {
std::cout << "Published documents do not need review again.\n";
}
void publish(Document& doc) override {
std::cout << "Document is already published.\n";
}
};
void DraftState::submitForReview(Document& doc) {
std::cout << "Submitting for review.\n";
doc.setState(std::make_unique<ModerationState>());
}
void ModerationState::approve(Document& doc) {
std::cout << "Review approved, document published.\n";
doc.setState(std::make_unique<PublishedState>());
}
void ModerationState::reject(Document& doc) {
std::cout << "Review rejected, returning to draft.\n";
doc.setState(std::make_unique<DraftState>());
}
int main() {
Document doc(std::make_unique<DraftState>());
std::cout << "Initial state: " << doc.getStateName() << "\n\n";
doc.edit();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
doc.publish();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
doc.submitForReview();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
doc.edit();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
doc.approve();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
doc.edit();
std::cout << "Current state: " << doc.getStateName() << "\n\n";
Document doc2(std::make_unique<DraftState>());
std::cout << "\n--- Demonstrating rejection path with a new document ---\n";
doc2.edit();
doc2.submitForReview();
doc2.reject();
std::cout << "Current state: " << doc2.getStateName() << "\n\n";
doc2.edit();
return 0;
}