I have built a simple finite state machine that models an even simpler fictitious bank account system.
Any given account can be in one of three states at any time: Open, Closed, or Held.
I have a few different methods that transition from one state to another:
- reopen: closed -> open
- close : open / held -> closed
- place_hold : open -> held
- remove_hold : held -> open
I have used an ES6 class and prototypes to implements this. three different objects, each with its own methods, are set to be the __proto__
of any given BankAccount
object.
The problem with this is that changing the __proto__
of an object removes its ability to call its class's methods, which is a problem.
Here is a stripped down version of my code:
const open ={stateName:"Open",
close: function(){
this.changeState(closed);
},
reopen: function(){
return;
},
place_hold: function(){
this.changeState(held);
},
remove_hold: function(){
return;
}
}
const held ={stateName:"Held",
close: function(){
this.changeState(closed);
},
reopen: function(){
return;
},
place_hold: function(){
return;
},
remove_hold: function(){
this.changeState(open);
}
}
const closed ={stateName:"Closed",
close: function(){
return;
},
reopen: function(){
this.changeState(open);
},
place_hold: function(){
return;
},
remove_hold: function(){
return;
}
}
class BankAccount {
constructor() {
this.balance = 0;
this.__proto__ = open;
this.changeState = state=>this.__proto__ = state;
}
otherStuff(){
// this cannot be called...
}
}
What would be a more proper way to do this, keeping our accounts able to access the class's methods, as well as the syntax used to access the methods implemented through the state machine?