I have a calculator app and I'm trying to apply the command pattern
I have a fully working version
Please help me figure out how I should do
How do I use the command pattern in my code?
CalculatorCore.js
class CalculatorModel {
constructor() {
this.currentValue = ''
this.result = ''
this.register = []
this.history = []
}
executedCommand(command) {
this.currentValue = command.execute(this.currentValue)
this.history.push({
command: command.name,
value: this.currentValue,
})
}
inputDigit(digit) {
if (isNaN(digit)) {
throw new Error('Digit is not a number')
}
if (this.result !== '') {
this.currentValue = ''
this.result = ''
}
this.currentValue += digit
}
inputDecimal() {
if (this.result !== '') {
this.currentValue = ''
this.result = ''
}
if (this.currentValue.indexOf('.') >= 0) {
return
}
if (this.currentValue === '') {
this.currentValue += '0.'
} else {
this.currentValue += '.'
}
}
clear() {
this.currentValue = ''
this.result = ''
this.register = []
}
clearAll() {
this.currentValue = ''
this.result = ''
this.register = []
this.history = []
}
delete() {
if (this.currentValue === '') {
return
}
this.currentValue = this.currentValue.slice(0, -1)
}
undo() {
if (this.history.length === 0) {
return
}
const lastCommand = this.history.pop()
this.currentValue = lastCommand.value
}
getResult() {
return this.result
}
add() {
if (this.currentValue === '') {
return
}
this.register.push(this.currentValue)
this.register.push('+')
this.currentValue = ''
}
subtract() {
if (this.currentValue === '') {
return
}
this.register.push(this.currentValue)
this.register.push('-')
this.currentValue = ''
}
multiply() {
if (this.currentValue === '') {
return
}
this.register.push(this.currentValue)
this.register.push('*')
this.currentValue = ''
}
divide() {
if (this.currentValue === '') {
return
}
this.register.push(this.currentValue)
this.register.push('/')
this.currentValue = ''
}
getHistory() {
return this.history
}
getRegister() {
return this.register
}
getCurrentValue() {
return this.currentValue
}
equals() {
if (this.currentValue === '') {
return
}
this.register.push(this.currentValue)
this.result = eval(this.register.join(''))
this.history.push({
expression: this.register.join(''),
result: this.result,
})
this.register = []
this.currentValue = this.result.toString()
}
toggleSign() {
this.currentValue = this.currentValue * -1
}
}
class AddCommand {
constructor(value) {
this.name = 'add'
this.value = value
}
execute(currentValue) {
return currentValue + this.value
}
undo() {
return this.currentValue - this.value
}
}
class SubtractCommand {
constructor(value) {
this.name = 'subtract'
this.value = value
}
execute(currentValue) {
return currentValue - this.value
}
undo() {
return this.currentValue + this.value
}
}
class MultiplyCommand {
constructor(value) {
this.name = 'multiply'
this.value = value
}
execute(currentValue) {
return currentValue * this.value
}
undo() {
return this.currentValue / this.value
}
}
class DivideCommand {
constructor(value) {
this.name = 'divide'
this.value = value
}
execute(currentValue) {
return currentValue / this.value
}
undo() {
return this.currentValue * this.value
}
}
class ClearCommand {
constructor() {
this.name = 'clear'
}
execute() {
return ''
}
undo() {
return this.currentValue
}
}
class ClearAllCommand {
constructor() {
this.name = 'clearAll'
}
execute() {
return ''
}
undo() {
return this.currentValue
}
}
class DeleteCommand {
constructor() {
this.name = 'delete'
}
execute(currentValue) {
return currentValue.slice(0, -1)
}
undo() {
return this.currentValue
}
}
class ToggleSignCommand {
constructor() {
this.name = 'toggleSign'
}
execute(currentValue) {
return currentValue * -1
}
undo() {
return this.currentValue
}
}
class EqualsCommand {
constructor() {
this.name = 'equals'
}
execute(currentValue) {
return currentValue
}
undo() {
return this.currentValue
}
}
class UndoCommand {
constructor() {
this.name = 'undo'
}
execute(currentValue) {
return currentValue
}
undo() {
return this.currentValue
}
}
export {
CalculatorModel,
AddCommand,
SubtractCommand,
MultiplyCommand,
DivideCommand,
ClearCommand,
ClearAllCommand,
DeleteCommand,
ToggleSignCommand,
EqualsCommand,
UndoCommand,
}
Calculator.jsx
export class Calculator extends Component {
constructor(props) {
super(props)
this.state = {
isHistoryOpen: false,
history: [],
formula: [],
input: '',
result: '',
}
this.handleDigit = this.handleDigit.bind(this)
this.handleClear = this.handleClear.bind(this)
this.handleDelete = this.handleDelete.bind(this)
this.handleToggleSign = this.handleToggleSign.bind(this)
this.handleOperator = this.handleOperator.bind(this)
this.handleDecimalPoint = this.handleDecimalPoint.bind(this)
this.handleEqual = this.handleEqual.bind(this)
this.handleHistoryClick = this.handleHistoryClick.bind(this)
}
handleDigit(number) {
calculator.executedCommand(new AddCommand(number))
this.setState(prevState => ({
input: prevState.input + number,
formula: prevState.formula.concat(number),
}))
}
handleClear() {
this.setState({
input: '',
formula: [],
result: '',
})
}
handleDelete() {
this.setState(prevState => ({
input: prevState.input.slice(0, -1),
}))
}
handleToggleSign() {
this.setState(prevState => ({
input:
prevState.input.charAt(0) === '-'
? prevState.input.slice(1)
: '-' + prevState.input,
}))
}
handleOperator(operator) {
this.setState(prevState => ({
input: prevState.input + operator,
}))
}
handleDecimalPoint() {
if (!this.state.input.includes('.')) {
this.setState(prevState => ({
input: prevState.input + '.',
}))
}
}
handleEqual() {
this.setState(prevState => ({
result: eval(prevState.input),
}))
this.setState(prevState => ({
history: [
...prevState.history,
{
input: prevState.input,
result: prevState.result,
},
],
}))
this.setState({
input: '',
})
}
handleHistoryClick() {
this.setState(prevState => ({
isHistoryOpen: !prevState.isHistoryOpen,
}))
}
render() {
return (
<Fragment>
<MainContainer>
<LeftSide>
<ControlPanel onHistoryClick={this.handleHistoryClick} />
<Display
result={this.state.result}
input={this.state.input}
formula={this.state.formula}
/>
<Keypad
onDigit={this.handleDigit}
onClear={this.handleClear}
onDelete={this.handleDelete}
onToggleSign={this.handleToggleSign}
onOperator={this.handleOperator}
onDecimalPoint={this.handleDecimalPoint}
onEqual={this.handleEqual}
/>
</LeftSide>
{this.state.isHistoryOpen && (
<History history={this.state.history} />
)}
</MainContainer>
</Fragment>
)
}
}
I have read and studied the pattern, but how should I apply it to my application, I cannot yet understand and deal with it