Skip to content

Commit 672390c

Browse files
Merge pull request #25 from darbyluv2code/feature/add-interpreter-pattern-v2
Add Interpreter Pattern with AND expression
2 parents d32efd9 + 89fc975 commit 672390c

10 files changed

Lines changed: 264 additions & 0 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.luv2code</groupId>
8+
<artifactId>java-design-patterns</artifactId>
9+
<version>1.0</version>
10+
11+
<properties>
12+
<maven.compiler.source>25</maven.compiler.source>
13+
<maven.compiler.target>25</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Non-Terminal expression (contains other rules)
5+
*
6+
* Interprets two expressions as a logical AND:
7+
* succeeds only if both left and right expressions succeed.
8+
*/
9+
public class AndExpression implements Expression {
10+
11+
private Expression leftExpression;
12+
private Expression rightExpression;
13+
14+
public AndExpression(Expression leftExpression, Expression rightExpression) {
15+
this.leftExpression = leftExpression;
16+
this.rightExpression = rightExpression;
17+
}
18+
19+
@Override
20+
public boolean interpret(ChatContext chatContext) {
21+
return leftExpression.interpret(chatContext) && rightExpression.interpret(chatContext);
22+
}
23+
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Context
5+
*
6+
* Holds the shared state passed to every expression during interpretation.
7+
*/
8+
public class ChatContext {
9+
10+
private String currentUser;
11+
12+
public ChatContext(String currentUser) {
13+
this.currentUser = currentUser;
14+
}
15+
16+
public String getCurrentUser() {
17+
return currentUser;
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Helper (Parser)
5+
*
6+
* Parses a raw command string and builds the appropriate Expression.
7+
*
8+
* Not part of the GoF pattern itself ... this is the caller that constructs
9+
* and triggers the expressions.
10+
*/
11+
public class CommandParser {
12+
13+
private static final String AND_SEPARATOR = " AND ";
14+
15+
public Expression parse(String inputCommand) {
16+
17+
if (inputCommand == null || inputCommand.isBlank()) {
18+
return new InvalidCommandExpression("empty input");
19+
}
20+
21+
String trimmedInput = inputCommand.trim();
22+
23+
// check for AND expressions
24+
int andIndex = trimmedInput.indexOf(AND_SEPARATOR);
25+
if (andIndex != -1) {
26+
// we found AND
27+
String leftInput = trimmedInput.substring(0, andIndex).trim();
28+
String rightInput = trimmedInput.substring(andIndex + AND_SEPARATOR.length()).trim();
29+
return new AndExpression(parse(leftInput), parse(rightInput));
30+
}
31+
32+
String[] parts = trimmedInput.split("\\s+", 2);
33+
34+
String commandName = parts[0];
35+
String argument = parts.length > 1 ? parts[1] : "";
36+
37+
return switch (commandName) {
38+
case "/join" -> new JoinExpression(argument);
39+
case "/mute" -> new MuteExpression(argument);
40+
case "/remind" -> new RemindExpression(argument);
41+
default -> new InvalidCommandExpression(commandName);
42+
};
43+
}
44+
}
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Abstract Expression
5+
*
6+
* Declares the interpret() method that all expressions must implement.
7+
*/
8+
public interface Expression {
9+
10+
boolean interpret(ChatContext chatContext);
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Concrete / Terminal Expression
5+
*
6+
* Handles unrecognized commands by reporting an error.
7+
*/
8+
public class InvalidCommandExpression implements Expression {
9+
10+
private String commandText;
11+
12+
public InvalidCommandExpression(String commandText) {
13+
this.commandText = commandText;
14+
}
15+
16+
@Override
17+
public boolean interpret(ChatContext chatContext) {
18+
System.out.println("[Error] Invalid command: " + commandText);
19+
20+
return false;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Concrete / Terminal Expression
5+
*
6+
* Handles the /join command by adding the user to a chat room.
7+
*/
8+
public class JoinExpression implements Expression {
9+
10+
private String roomName;
11+
12+
public JoinExpression(String roomName) {
13+
this.roomName = roomName;
14+
}
15+
16+
@Override
17+
public boolean interpret(ChatContext chatContext) {
18+
System.out.println("[Join] " + chatContext.getCurrentUser()
19+
+ " joined room: " + roomName);
20+
21+
return true;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Client
5+
*
6+
* Drives the demo by sending sample chat commands through the interpreter.
7+
*/
8+
public class MainApp {
9+
10+
static void main() {
11+
12+
System.out.println("--- Demo: Chat Command Interpreter ---");
13+
14+
CommandParser commandParser = new CommandParser();
15+
16+
runCommand("/join java-room", "Angel", commandParser);
17+
runCommand("/mute Liam", "Angel", commandParser);
18+
runCommand("/remind Team meeting at 3pm", "Angel", commandParser);
19+
runCommand("/dance now", "Angel", commandParser);
20+
21+
System.out.println("\n--- Demo: Chained Commands with AND ---");
22+
runCommand("/join python-room AND /remind Customer meeting at 10am",
23+
"Peter", commandParser);
24+
25+
}
26+
27+
private static void runCommand(String inputCommand,
28+
String currentUser,
29+
CommandParser commandParser) {
30+
31+
ChatContext chatContext = new ChatContext(currentUser);
32+
33+
System.out.println("\nInput: " + inputCommand);
34+
35+
Expression parsedExpression = commandParser.parse(inputCommand);
36+
parsedExpression.interpret(chatContext);
37+
}
38+
}
39+
40+
41+
42+
43+
44+
45+
46+
47+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Concrete / Terminal Expression
5+
*
6+
* Handles the /mute command by silencing a target user.
7+
*/
8+
public class MuteExpression implements Expression {
9+
10+
private String targetUser;
11+
12+
public MuteExpression(String targetUser) {
13+
this.targetUser = targetUser;
14+
}
15+
16+
@Override
17+
public boolean interpret(ChatContext chatContext) {
18+
System.out.println("[Mute] " + chatContext.getCurrentUser()
19+
+ " muted user: " + targetUser);
20+
21+
return true;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.luv2code.designpatterns.behavioral.interpreter.v2_advanced_with_and_expression;
2+
3+
/**
4+
* Role: Concrete / Terminal Expression
5+
*
6+
* Handles the /remind command by creating a reminder for the current user.
7+
*/
8+
public class RemindExpression implements Expression {
9+
10+
private String reminderText;
11+
12+
public RemindExpression(String reminderText) {
13+
this.reminderText = reminderText;
14+
}
15+
16+
@Override
17+
public boolean interpret(ChatContext chatContext) {
18+
System.out.println("[Remind] Reminder created for "
19+
+ chatContext.getCurrentUser() + ": " + reminderText);
20+
21+
return true;
22+
}
23+
}

0 commit comments

Comments
 (0)