Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/main/java/com/smarthome/command/GetStatusCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.smarthome.model.LightState;
import com.smarthome.service.LightService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* GetStatusCommand - A Concrete Command to get the current light status.
Expand All @@ -11,7 +13,11 @@
*
* STRICT DECOUPLING: This allows the Controller to get status
* without having any direct reference to the LightService.
*
* SPRING BEAN: This command is a Spring-managed bean (@Component) that
* is injected with the LightService (Receiver) dependency.
*/
@Component
public class GetStatusCommand implements Command {

/**
Expand All @@ -21,9 +27,11 @@ public class GetStatusCommand implements Command {

/**
* Constructor that receives the Receiver (LightService) as a dependency.
* Spring will inject the LightService bean automatically.
*
* @param lightService The service that holds the light state
*/
@Autowired
public GetStatusCommand(LightService lightService) {
this.lightService = lightService;
}
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/smarthome/command/LightOffCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.smarthome.model.LightState;
import com.smarthome.service.LightService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* LightOffCommand - A Concrete Command in the Command Design Pattern.
Expand All @@ -10,10 +12,14 @@
* It holds a reference to the Receiver (LightService) and delegates
* the actual work to it.
*
* STRICT DECOUPLING: The Controller (Invoker) doesn't need to know about
* STRICT DECOUPLING: The Controller (Client) doesn't need to know about
* the LightService. It only knows about the Command interface.
* This command handles all interaction with the Receiver internally.
*
* SPRING BEAN: This command is a Spring-managed bean (@Component) that
* is injected with the LightService (Receiver) dependency.
*/
@Component
public class LightOffCommand implements Command {

/**
Expand All @@ -23,9 +29,11 @@ public class LightOffCommand implements Command {

/**
* Constructor that receives the Receiver (LightService) as a dependency.
* Spring will inject the LightService bean automatically.
*
* @param lightService The service that will perform the actual operation
*/
@Autowired
public LightOffCommand(LightService lightService) {
this.lightService = lightService;
}
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/smarthome/command/LightOnCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.smarthome.model.LightState;
import com.smarthome.service.LightService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* LightOnCommand - A Concrete Command in the Command Design Pattern.
Expand All @@ -10,10 +12,14 @@
* It holds a reference to the Receiver (LightService) and delegates
* the actual work to it.
*
* STRICT DECOUPLING: The Controller (Invoker) doesn't need to know about
* STRICT DECOUPLING: The Controller (Client) doesn't need to know about
* the LightService. It only knows about the Command interface.
* This command handles all interaction with the Receiver internally.
*
* SPRING BEAN: This command is a Spring-managed bean (@Component) that
* is injected with the LightService (Receiver) dependency.
*/
@Component
public class LightOnCommand implements Command {

/**
Expand All @@ -23,9 +29,11 @@ public class LightOnCommand implements Command {

/**
* Constructor that receives the Receiver (LightService) as a dependency.
* Spring will inject the LightService bean automatically.
*
* @param lightService The service that will perform the actual operation
*/
@Autowired
public LightOnCommand(LightService lightService) {
this.lightService = lightService;
}
Expand Down
102 changes: 71 additions & 31 deletions src/main/java/com/smarthome/controller/DashboardController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.smarthome.controller;

import com.smarthome.command.Command;
import com.smarthome.command.GetStatusCommand;
import com.smarthome.command.LightOffCommand;
import com.smarthome.command.LightOnCommand;
import com.smarthome.invoker.CommandInvoker;
import com.smarthome.model.LightState;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -10,9 +14,10 @@
/**
* DashboardController - The Client in the Strict Command Design Pattern.
*
* REFACTORED ARCHITECTURE:
* REFACTORED ARCHITECTURE (Per UML Class Diagram):
* - The Controller acts as a CLIENT, not an Invoker
* - The Controller delegates command creation and execution to the CommandInvoker
* - The Controller has reference to Command beans (injected by Spring)
* - The Controller delegates command queuing and execution to the CommandInvoker
* - The Controller has NO direct dependency on the Receiver (LightService)
* - All communication with the Receiver happens through Commands via the Invoker
*
Expand All @@ -21,9 +26,10 @@
* - Returns View names, not raw data
* - Uses Spring's Model to pass data to the View
*
* EXECUTION FLOW:
* Controller -> Creates Command via Invoker -> Pushes Command to Invoker -> Invoker processes Queue
* -> Command calls Receiver -> Receiver updates Model
* EXECUTION FLOW (Per UML Sequence Diagram):
* Controller -> Sets Command via setCommand() -> Pushes Command via pushCurrentCommand()
* -> Invoker queues Command -> Controller triggers executeCommands()
* -> Invoker processes Queue (FIFO) -> Command calls Receiver -> Returns LightState
*
* DECOUPLING BENEFITS:
* - Controller doesn't know HOW to control the light
Expand All @@ -35,31 +41,59 @@
public class DashboardController {

/**
* The CommandInvoker manages command creation, queue, and execution.
* Controller creates commands via the Invoker and triggers execution.
* The CommandInvoker manages command queue and execution.
* Controller sets commands on the Invoker and triggers execution.
*/
private final CommandInvoker commandInvoker;

/**
* Command bean reference for getting light status (per UML: -command: Command).
* Injected by Spring as a managed bean.
*/
private final Command getStatusCommand;

/**
* Command bean reference for turning light ON (per UML: -command: Command).
* Injected by Spring as a managed bean.
*/
private final Command lightOnCommand;

/**
* Command bean reference for turning light OFF (per UML: -command: Command).
* Injected by Spring as a managed bean.
*/
private final Command lightOffCommand;

/**
* Constructor-based dependency injection.
* The Controller only needs the CommandInvoker - it doesn't know about LightService.
* The Controller receives the CommandInvoker and Command beans.
* NOTE: The Controller does NOT receive LightService - strict decoupling.
*
* @param commandInvoker The dedicated Invoker for command creation and execution
* @param commandInvoker The dedicated Invoker for command queuing and execution
* @param getStatusCommand The command bean for getting light status
* @param lightOnCommand The command bean for turning light ON
* @param lightOffCommand The command bean for turning light OFF
*/
@Autowired
public DashboardController(CommandInvoker commandInvoker) {
public DashboardController(CommandInvoker commandInvoker,
GetStatusCommand getStatusCommand,
LightOnCommand lightOnCommand,
LightOffCommand lightOffCommand) {
this.commandInvoker = commandInvoker;
this.getStatusCommand = getStatusCommand;
this.lightOnCommand = lightOnCommand;
this.lightOffCommand = lightOffCommand;
}

/**
* Displays the Smart Home Dashboard.
*
* REFACTORED COMMAND PATTERN FLOW:
* COMMAND PATTERN FLOW (Per UML Sequence Diagram):
* 1. User navigates to /dashboard
* 2. Controller creates a GET_STATUS command via the Invoker
* 3. Controller pushes Command to CommandInvoker
* 4. Controller triggers execution via the Invoker
* 5. Invoker executes Command from queue
* 2. Controller sets the GET_STATUS command via invoker.setCommand()
* 3. Controller pushes Command to queue via invoker.pushCurrentCommand()
* 4. Controller triggers execution via invoker.executeCommands()
* 5. Invoker processes queue (FIFO) and executes Command
* 6. Command returns LightState (Model)
* 7. Controller adds Model to Spring's Model
* 8. Controller returns "dashboard" (View name)
Expand All @@ -71,9 +105,11 @@ public DashboardController(CommandInvoker commandInvoker) {
*/
@GetMapping("/dashboard")
public String showDashboard(Model model) {
// Create command via Invoker, push, and execute
commandInvoker.createCommand(CommandInvoker.CommandType.GET_STATUS);
// Set command via Invoker (per UML: setCommand)
commandInvoker.setCommand(getStatusCommand);
// Push command to queue (per UML: pushCurrentCommand)
commandInvoker.pushCurrentCommand();
// Execute commands and get result (per UML: executeCommands)
LightState lightState = commandInvoker.executeCommands();

// Add Model to Spring's Model for the View
Expand All @@ -86,12 +122,12 @@ public String showDashboard(Model model) {
/**
* Turns ON the light and returns to dashboard.
*
* REFACTORED COMMAND PATTERN FLOW:
* COMMAND PATTERN FLOW (Per UML Sequence Diagram):
* 1. User clicks "Turn ON" button on View
* 2. Controller creates a LIGHT_ON command via the Invoker
* 3. Controller pushes Command to CommandInvoker
* 4. Controller triggers execution via the Invoker
* 5. Invoker executes Command from queue
* 2. Controller sets the LIGHT_ON command via invoker.setCommand()
* 3. Controller pushes Command to queue via invoker.pushCurrentCommand()
* 4. Controller triggers execution via invoker.executeCommands()
* 5. Invoker processes queue (FIFO) and executes Command
* 6. Command delegates to Receiver (internally)
* 7. Command returns LightState (Model)
* 8. Controller returns "dashboard" (View name)
Expand All @@ -104,9 +140,11 @@ public String showDashboard(Model model) {
*/
@GetMapping("/light/on")
public String turnLightOn(Model model) {
// Create command via Invoker, push, and execute
commandInvoker.createCommand(CommandInvoker.CommandType.LIGHT_ON);
// Set command via Invoker (per UML: setCommand)
commandInvoker.setCommand(lightOnCommand);
// Push command to queue (per UML: pushCurrentCommand)
commandInvoker.pushCurrentCommand();
// Execute commands and get result (per UML: executeCommands)
LightState lightState = commandInvoker.executeCommands();

// Add Model to Spring's Model for the View
Expand All @@ -119,12 +157,12 @@ public String turnLightOn(Model model) {
/**
* Turns OFF the light and returns to dashboard.
*
* REFACTORED COMMAND PATTERN FLOW:
* COMMAND PATTERN FLOW (Per UML Sequence Diagram):
* 1. User clicks "Turn OFF" button on View
* 2. Controller creates a LIGHT_OFF command via the Invoker
* 3. Controller pushes Command to CommandInvoker
* 4. Controller triggers execution via the Invoker
* 5. Invoker executes Command from queue
* 2. Controller sets the LIGHT_OFF command via invoker.setCommand()
* 3. Controller pushes Command to queue via invoker.pushCurrentCommand()
* 4. Controller triggers execution via invoker.executeCommands()
* 5. Invoker processes queue (FIFO) and executes Command
* 6. Command delegates to Receiver (internally)
* 7. Command returns LightState (Model)
* 8. Controller returns "dashboard" (View name)
Expand All @@ -137,9 +175,11 @@ public String turnLightOn(Model model) {
*/
@GetMapping("/light/off")
public String turnLightOff(Model model) {
// Create command via Invoker, push, and execute
commandInvoker.createCommand(CommandInvoker.CommandType.LIGHT_OFF);
// Set command via Invoker (per UML: setCommand)
commandInvoker.setCommand(lightOffCommand);
// Push command to queue (per UML: pushCurrentCommand)
commandInvoker.pushCurrentCommand();
// Execute commands and get result (per UML: executeCommands)
LightState lightState = commandInvoker.executeCommands();

// Add Model to Spring's Model for the View
Expand Down
Loading