From e93f2da595a12c312dfeb776afffe6d5c23b6fdd Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 20 Nov 2022 02:40:58 +0300 Subject: [PATCH] state gummball --- README.md | 1 + state/README.md | 5 + state/gumballmachine/app.d | 40 +++++ state/gumballmachine/gumballmachine.d | 155 ++++++++++++++++++++ state/gumballmachinestate/app.d | 27 ++++ state/gumballmachinestate/gumballmachine.d | 116 +++++++++++++++ state/gumballmachinestate/hasquarterstate.d | 43 ++++++ state/gumballmachinestate/noquarterstate.d | 42 ++++++ state/gumballmachinestate/soldoutstate.d | 44 ++++++ state/gumballmachinestate/soldstate.d | 50 +++++++ state/gumballmachinestate/state.d | 11 ++ 11 files changed, 534 insertions(+) create mode 100644 state/README.md create mode 100644 state/gumballmachine/app.d create mode 100644 state/gumballmachine/gumballmachine.d create mode 100644 state/gumballmachinestate/app.d create mode 100644 state/gumballmachinestate/gumballmachine.d create mode 100644 state/gumballmachinestate/hasquarterstate.d create mode 100644 state/gumballmachinestate/noquarterstate.d create mode 100644 state/gumballmachinestate/soldoutstate.d create mode 100644 state/gumballmachinestate/soldstate.d create mode 100644 state/gumballmachinestate/state.d diff --git a/README.md b/README.md index 2178d4c..948698d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ 3. [Команда](command/) 4. [Шаблонный метод](templatemethod/) 5. [Итератор](iterator/) +6. [Состояние](state/) ### Структурные diff --git a/state/README.md b/state/README.md new file mode 100644 index 0000000..9cd1f3b --- /dev/null +++ b/state/README.md @@ -0,0 +1,5 @@ +# Состояние + +Поведенческий паттерн проектирования, который позволяет объектам менять поведение в зависимости от своего состояния. Извне создаётся впечатление, что изменился класс объекта. + + diff --git a/state/gumballmachine/app.d b/state/gumballmachine/app.d new file mode 100644 index 0000000..595958b --- /dev/null +++ b/state/gumballmachine/app.d @@ -0,0 +1,40 @@ +module app; + +import gumballmachine; +import std.stdio : writeln; + +void main() +{ + GumballMachine gumballMachine = new GumballMachine(5); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.ejectQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.ejectQuarter(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); +} diff --git a/state/gumballmachine/gumballmachine.d b/state/gumballmachine/gumballmachine.d new file mode 100644 index 0000000..8a4d30b --- /dev/null +++ b/state/gumballmachine/gumballmachine.d @@ -0,0 +1,155 @@ +module gumballmachine; + +import std.stdio : writeln; +import std.conv : to; + +class GumballMachine +{ + static const int SOLD_OUT = 0; // нет шариков + static const int NO_QUARTER = 1; // нет монетки + static const int HAS_QUARTER = 2; // есть монетка + static const int SOLD = 3; // шарик продан + + int state = SOLD_OUT; + int count = 0; + + this(int count) + { + this.count = count; + if (count > 0) + { + state = NO_QUARTER; + } + } + + void insertQuarter() + { + if (state == HAS_QUARTER) + { + writeln("You can't insert another quarter"); + } + else if (state == NO_QUARTER) + { + state = HAS_QUARTER; + writeln("You inserted a quarter"); + } + else if (state == SOLD_OUT) + { + writeln("You can't insert a quarter, the machine is sold out"); + } + else if (state == SOLD) + { + writeln("Please wait, we're already giving you a gumball"); + } + } + + void ejectQuarter() + { + if (state == HAS_QUARTER) + { + writeln("Quarter returned"); + state = NO_QUARTER; + } + else if (state == NO_QUARTER) + { + writeln("You haven't inserted a quarter"); + } + else if (state == SOLD) + { + writeln("Sorry, you already turned the crank"); + } + else if (state == SOLD_OUT) + { + writeln("You can't eject, you haven't inserted a quarter yet"); + } + } + + void turnCrank() + { + if (state == SOLD) + { + writeln("Turning twice doesn't get you another gumball!"); + } + else if (state == NO_QUARTER) + { + writeln("You turned but there's no quarter"); + } + else if (state == SOLD_OUT) + { + writeln("You turned, but there are no gumballs"); + } + else if (state == HAS_QUARTER) + { + writeln("You turned..."); + state = SOLD; + dispense(); + } + } + + private void dispense() + { + if (state == SOLD) + { + writeln("A gumball comes rolling out the slot"); + --count; + if (count == 0) + { + writeln("Oops, out of gumballs!"); + state = SOLD_OUT; + } + else + { + state = NO_QUARTER; + } + } + else if (state == NO_QUARTER) + { + writeln("You need to pay first"); + } + else if (state == SOLD_OUT) + { + writeln("No gumball dispensed"); + } + else if (state == HAS_QUARTER) + { + writeln("No gumball dispensed"); + } + } + + void refill(int numGumBalls) + { + this.count = numGumBalls; + state = NO_QUARTER; + } + + override string toString() const + { + string s; + s ~= "\nMighty Gumball, Inc."; + s ~= "\nJava-enabled Standing Gumball Model #2004\n"; + s ~= "Inventory: " ~ count.to!string ~ " gumball"; + if (count != 1) + { + s ~= "s"; + } + s ~= "\nMachine is "; + if (state == SOLD_OUT) + { + s ~= "sold out"; + } + else if (state == NO_QUARTER) + { + s ~= "waiting for quarter"; + } + else if (state == HAS_QUARTER) + { + s ~= "waiting for turn of crank"; + } + else if (state == SOLD) + { + s ~= "delivering a gumball"; + } + s ~= "\n"; + return s; + } +} diff --git a/state/gumballmachinestate/app.d b/state/gumballmachinestate/app.d new file mode 100644 index 0000000..43272c0 --- /dev/null +++ b/state/gumballmachinestate/app.d @@ -0,0 +1,27 @@ +module app; + +import gumballmachine; +import std.stdio : writeln; + +void main() +{ + GumballMachine gumballMachine = new GumballMachine(2); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); + + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + gumballMachine.refill(5); + gumballMachine.insertQuarter(); + gumballMachine.turnCrank(); + + writeln(gumballMachine); +} diff --git a/state/gumballmachinestate/gumballmachine.d b/state/gumballmachinestate/gumballmachine.d new file mode 100644 index 0000000..8423f38 --- /dev/null +++ b/state/gumballmachinestate/gumballmachine.d @@ -0,0 +1,116 @@ +module gumballmachine; + +import std.stdio : writeln; +import std.conv : to; +import soldoutstate, noquarterstate, hasquarterstate, soldstate, state; + +class GumballMachine +{ + State soldOutState; + State noQuarterState; + State hasQuarterState; + State soldState; + + State state; + int count = 0; + + this(int numberGumballs) + { + soldOutState = new SoldOutState(this); + noQuarterState = new NoQuarterState(this); + hasQuarterState = new HasQuarterState(this); + soldState = new SoldState(this); + + this.count = numberGumballs; + if (numberGumballs > 0) + { + state = noQuarterState; + } + else + { + state = soldOutState; + } + } + + void insertQuarter() + { + state.insertQuarter(); + } + + void ejectQuarter() + { + state.ejectQuarter(); + } + + void turnCrank() + { + state.turnCrank(); + state.dispense(); + } + + void releaseBall() + { + writeln("A gumball comes rolling out the slot..."); + if (count > 0) + { + count = count - 1; + } + } + + int getCount() + { + return count; + } + + void refill(int count) + { + this.count += count; + writeln("The gumball machine was just refilled; its new count is: ", this.count); + state.refill(); + } + + void setState(State state) + { + this.state = state; + } + + State getState() + { + return state; + } + + State getSoldOutState() + { + return soldOutState; + } + + State getNoQuarterState() + { + return noQuarterState; + } + + State getHasQuarterState() + { + return hasQuarterState; + } + + State getSoldState() + { + return soldState; + } + + override string toString() const + { + string s; + s ~= "\nMighty Gumball, Inc."; + s ~= "\nJava-enabled Standing Gumball Model #2004"; + s ~= "\nInventory: " ~ count.to!string ~ " gumball"; + if (count != 1) + { + s ~= "s"; + } + s ~= "\n"; + s ~= "Machine is " ~ state.to!string ~ "\n"; + return s; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/hasquarterstate.d b/state/gumballmachinestate/hasquarterstate.d new file mode 100644 index 0000000..6f6508c --- /dev/null +++ b/state/gumballmachinestate/hasquarterstate.d @@ -0,0 +1,43 @@ +module hasquarterstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class HasQuarterState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("You can't insert another quarter"); + } + + void ejectQuarter() + { + writeln("Quarter returned"); + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + void turnCrank() + { + writeln("You turned..."); + gumballMachine.setState(gumballMachine.getSoldState()); + } + + void dispense() + { + writeln("No gumball dispensed"); + } + + void refill() {} + + override string toString() const + { + return "waiting for turn of crank"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/noquarterstate.d b/state/gumballmachinestate/noquarterstate.d new file mode 100644 index 0000000..b3ead62 --- /dev/null +++ b/state/gumballmachinestate/noquarterstate.d @@ -0,0 +1,42 @@ +module noquarterstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class NoQuarterState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("You inserted a quarter"); + gumballMachine.setState(gumballMachine.getHasQuarterState()); + } + + void ejectQuarter() + { + writeln("You haven't inserted a quarter"); + } + + void turnCrank() + { + writeln("You turned, but there's no quarter"); + } + + void dispense() + { + writeln("You need to pay first"); + } + + void refill() { } + + override string toString() const + { + return "waiting for quarter"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/soldoutstate.d b/state/gumballmachinestate/soldoutstate.d new file mode 100644 index 0000000..4f3bace --- /dev/null +++ b/state/gumballmachinestate/soldoutstate.d @@ -0,0 +1,44 @@ +module soldoutstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldOutState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("You can't insert a quarter, the machine is sold out"); + } + + void ejectQuarter() + { + writeln("You can't eject, you haven't inserted a quarter yet"); + } + + void turnCrank() + { + writeln("You turned, but there are no gumballs"); + } + + void dispense() + { + writeln("No gumball dispensed"); + } + + void refill() + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + + override string toString() const + { + return "sold out"; + } +} diff --git a/state/gumballmachinestate/soldstate.d b/state/gumballmachinestate/soldstate.d new file mode 100644 index 0000000..73bab9f --- /dev/null +++ b/state/gumballmachinestate/soldstate.d @@ -0,0 +1,50 @@ +module soldstate; + +import std.stdio : writeln; +import state, gumballmachine; + +class SoldState : State +{ + GumballMachine gumballMachine; + + this(GumballMachine gumballMachine) + { + this.gumballMachine = gumballMachine; + } + + void insertQuarter() + { + writeln("Please wait, we're already giving you a gumball"); + } + + void ejectQuarter() + { + writeln("Sorry, you already turned the crank"); + } + + void turnCrank() + { + writeln("Turning twice doesn't get you another gumball!"); + } + + void dispense() + { + gumballMachine.releaseBall(); + if (gumballMachine.getCount() > 0) + { + gumballMachine.setState(gumballMachine.getNoQuarterState()); + } + else + { + writeln("Oops, out of gumballs!"); + gumballMachine.setState(gumballMachine.getSoldOutState()); + } + } + + void refill() {} + + override string toString() const + { + return "dispensing a gumball"; + } +} \ No newline at end of file diff --git a/state/gumballmachinestate/state.d b/state/gumballmachinestate/state.d new file mode 100644 index 0000000..813481d --- /dev/null +++ b/state/gumballmachinestate/state.d @@ -0,0 +1,11 @@ +module state; + +interface State +{ + void insertQuarter(); + void ejectQuarter(); + void turnCrank(); + void dispense(); + + void refill(); +}