SlideShare a Scribd company logo
The State Pattern
1
What is the State Pattern?
• One of the GoF Design Patterns
• Helps to organize code that handles multiple states
• Suitable for a code base where there are a lot of:
• Boolean flags or enum fields used to determine the state
• Similar if/switch conditionals based on the state
• Unclear state transitions
• Giant classes causing maintainability issues
2
Participants of the State Pattern
• Context
• Provides the public API of the application
• Holds a reference to current state object,
forwards API calls to it
• State
• Defines part of the API whose behavior must be
changed depending on the state
• ConcreteStates
• Exists for each possible state of the application
• Handles the API calls according to the state it
corresponds to
• Triggers a state transition
3
Case study: the SMTP protocol
S: 220 smtp.example.com ESMTP Postfix
C: HELO relay.example.com
S: 250 smtp.example.com, I am glad to meet you
C: MAIL FROM:<bob@example.com>
S: 250 Ok
C: RCPT TO:<alice@example.com>
S: 250 Ok
C: RCPT TO:<theboss@example.com>
S: 250 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: "Bob Example" <bob@example.com>
C: To: Alice Example <alice@example.com>
C: Cc: theboss@example.com
C: Date: Tue, 15 Jan 2008 16:02:43 -0500
C: Subject: Test message
C:
C: Hello Alice.
C: This is a test message with 5 header fields and 4 lines in the message body.
C: Your friend,
C: Bob
C: .
S: 250 Ok: queued as 12345
C: QUIT
S: 221 Bye
{The server closes the connection}
Taken from https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol
4
Implementing an SMTP server with the State Pattern (1/4)
public class SMTPSessionHandler {
private State currentState = new IdleState();
public String handleCommand(String command) {
return currentState.handleCommand(command, this);
}
void setCurrentState(State newState) {
this.currentState = newState;
}
}
interface State {
String handleCommand(String command, SMTPSessionHandler context);
}
5
class IdleState implements State {
@Override
public String handleCommand(String command, SMTPSessionHandler context) {
if (command.startsWith("HELO")) {
context.setCurrentState(new InitialState());
return "250 smtp.example.com, I am glad to meet you";
} else {
return "500 5.5.1 Invalid command";
}
}
}
class InitialState implements State {
private static final Pattern PATTERN_FOR_EXTRACTING_EMAIL = Pattern.compile("MAIL FROM:<([^>]+)>");
@Override
public String handleCommand(String command, SMTPSessionHandler context) {
Matcher matcher = PATTERN_FOR_EXTRACTING_EMAIL.matcher(command);
if (matcher.find()) {
String from = matcher.group(1);
context.setCurrentState(new TransactionStartedState(from));
return "250 Ok";
} else {
return "500 5.5.1 Invalid command";
}
}
}
6
Implementing an SMTP server with the State Pattern (2/4)
7
Implementing an SMTP server with the State Pattern (3/4)
class TransactionStartedState implements State {
private static final Pattern PATTERN_FOR_EXTRACTING_EMAIL =Pattern.compile("RCPT TO:<([^>]+)>");
private final String from;
private final List<String> destinations = new ArrayList<>();
TransactionStartedState(String from) { this.from = from; }
@Override
public String handleCommand(String command, SMTPSessionHandler context) {
if (command.equals("DATA")) {
if (destinations.isEmpty()) {
return "500 5.5.1 Invalid command";
} else {
context.setCurrentState(new DataTransferState(from, destinations));
return "354 End data with <CR><LF>.<CR><LF>";
}
}
Matcher matcher = PATTERN_FOR_EXTRACTING_EMAIL.matcher(command);
if (matcher.find()) {
String to = matcher.group(1);
destinations.add(to);
return "250 Ok";
} else {
return "500 5.5.1 Invalid command";
}
}
}
class DataTransferState implements State {
private final String from;
private final List<String> destinations;
private final StringBuilder body = new StringBuilder();
static DeliverySystem deliverySystem = (from, destinations, body) -> {
// looks up MX records, connects to external SMTP servers and relays the message
};
DataTransferState(String from, List<String> destinations) {
this.from = from;
this.destinations = destinations;
}
@Override
public String handleCommand(String command, SMTPSessionHandler context) {
if (command.equals(".")) {
deliverySystem.deliver(from, destinations, body.toString());
context.setCurrentState(new InitialState());
return "250 Ok: the email has been delivered";
} else {
body.append(command);
body.append('n');
return null;
}
}
}
8
Implementing an SMTP server with the State Pattern (4/4)
Conclusion: benefits of the State Pattern
• Concise and short classes with clear responsibility
• Clear state transition
• Better maintainability
• You can write a new concrete state class for a new state
• There will be no giant classes
9

More Related Content

PPTX
Function Parameters
PPTX
Functions
PPTX
Function Returns
PPT
Evolution of asynchrony in (ASP).NET
PPSX
Sql triggers
PDF
Postman tests in jenkins
PPT
Asynchronous t sql
PPTX
AMC Minor Technical Issues
Function Parameters
Functions
Function Returns
Evolution of asynchrony in (ASP).NET
Sql triggers
Postman tests in jenkins
Asynchronous t sql
AMC Minor Technical Issues

Similar to The State Pattern (20)

PPT
PDF
ERRest - Designing a good REST service
PPTX
Apex Testing and Best Practices
PPTX
JDBC ResultSet power point presentation by klu
PPT
JDBC Java Database Connectivity
PPT
MySQLi - An Improved Extension of MySQL
ODP
jQuery : Talk to server with Ajax
DOC
PPT
Sqlapi0.1
PPT
Spring Capitulo 05
PDF
JUnit and Mockito tips
ODP
Ast transformation
PDF
Tdd iPhone For Dummies
DOCX
My java file
PPT
Taming Deployment With Smart Frog
PDF
Bot builder v4 HOL
PPT
Smtp
PPT
my accadanic project ppt
PDF
Pretenders talk at PyconUK 2012
PPTX
13 networking, mobile services, and authentication
ERRest - Designing a good REST service
Apex Testing and Best Practices
JDBC ResultSet power point presentation by klu
JDBC Java Database Connectivity
MySQLi - An Improved Extension of MySQL
jQuery : Talk to server with Ajax
Sqlapi0.1
Spring Capitulo 05
JUnit and Mockito tips
Ast transformation
Tdd iPhone For Dummies
My java file
Taming Deployment With Smart Frog
Bot builder v4 HOL
Smtp
my accadanic project ppt
Pretenders talk at PyconUK 2012
13 networking, mobile services, and authentication
Ad

Recently uploaded (20)

PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
history of c programming in notes for students .pptx
PDF
System and Network Administration Chapter 2
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Introduction to Artificial Intelligence
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Wondershare Filmora 15 Crack With Activation Key [2025
CHAPTER 2 - PM Management and IT Context
Understanding Forklifts - TECH EHS Solution
Navsoft: AI-Powered Business Solutions & Custom Software Development
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
VVF-Customer-Presentation2025-Ver1.9.pptx
Design an Analysis of Algorithms II-SECS-1021-03
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
history of c programming in notes for students .pptx
System and Network Administration Chapter 2
Softaken Excel to vCard Converter Software.pdf
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Operating system designcfffgfgggggggvggggggggg
Upgrade and Innovation Strategies for SAP ERP Customers
L1 - Introduction to python Backend.pptx
Introduction to Artificial Intelligence
Odoo POS Development Services by CandidRoot Solutions
Which alternative to Crystal Reports is best for small or large businesses.pdf
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Ad

The State Pattern

  • 2. What is the State Pattern? • One of the GoF Design Patterns • Helps to organize code that handles multiple states • Suitable for a code base where there are a lot of: • Boolean flags or enum fields used to determine the state • Similar if/switch conditionals based on the state • Unclear state transitions • Giant classes causing maintainability issues 2
  • 3. Participants of the State Pattern • Context • Provides the public API of the application • Holds a reference to current state object, forwards API calls to it • State • Defines part of the API whose behavior must be changed depending on the state • ConcreteStates • Exists for each possible state of the application • Handles the API calls according to the state it corresponds to • Triggers a state transition 3
  • 4. Case study: the SMTP protocol S: 220 smtp.example.com ESMTP Postfix C: HELO relay.example.com S: 250 smtp.example.com, I am glad to meet you C: MAIL FROM:<bob@example.com> S: 250 Ok C: RCPT TO:<alice@example.com> S: 250 Ok C: RCPT TO:<theboss@example.com> S: 250 Ok C: DATA S: 354 End data with <CR><LF>.<CR><LF> C: From: "Bob Example" <bob@example.com> C: To: Alice Example <alice@example.com> C: Cc: theboss@example.com C: Date: Tue, 15 Jan 2008 16:02:43 -0500 C: Subject: Test message C: C: Hello Alice. C: This is a test message with 5 header fields and 4 lines in the message body. C: Your friend, C: Bob C: . S: 250 Ok: queued as 12345 C: QUIT S: 221 Bye {The server closes the connection} Taken from https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol 4
  • 5. Implementing an SMTP server with the State Pattern (1/4) public class SMTPSessionHandler { private State currentState = new IdleState(); public String handleCommand(String command) { return currentState.handleCommand(command, this); } void setCurrentState(State newState) { this.currentState = newState; } } interface State { String handleCommand(String command, SMTPSessionHandler context); } 5
  • 6. class IdleState implements State { @Override public String handleCommand(String command, SMTPSessionHandler context) { if (command.startsWith("HELO")) { context.setCurrentState(new InitialState()); return "250 smtp.example.com, I am glad to meet you"; } else { return "500 5.5.1 Invalid command"; } } } class InitialState implements State { private static final Pattern PATTERN_FOR_EXTRACTING_EMAIL = Pattern.compile("MAIL FROM:<([^>]+)>"); @Override public String handleCommand(String command, SMTPSessionHandler context) { Matcher matcher = PATTERN_FOR_EXTRACTING_EMAIL.matcher(command); if (matcher.find()) { String from = matcher.group(1); context.setCurrentState(new TransactionStartedState(from)); return "250 Ok"; } else { return "500 5.5.1 Invalid command"; } } } 6 Implementing an SMTP server with the State Pattern (2/4)
  • 7. 7 Implementing an SMTP server with the State Pattern (3/4) class TransactionStartedState implements State { private static final Pattern PATTERN_FOR_EXTRACTING_EMAIL =Pattern.compile("RCPT TO:<([^>]+)>"); private final String from; private final List<String> destinations = new ArrayList<>(); TransactionStartedState(String from) { this.from = from; } @Override public String handleCommand(String command, SMTPSessionHandler context) { if (command.equals("DATA")) { if (destinations.isEmpty()) { return "500 5.5.1 Invalid command"; } else { context.setCurrentState(new DataTransferState(from, destinations)); return "354 End data with <CR><LF>.<CR><LF>"; } } Matcher matcher = PATTERN_FOR_EXTRACTING_EMAIL.matcher(command); if (matcher.find()) { String to = matcher.group(1); destinations.add(to); return "250 Ok"; } else { return "500 5.5.1 Invalid command"; } } }
  • 8. class DataTransferState implements State { private final String from; private final List<String> destinations; private final StringBuilder body = new StringBuilder(); static DeliverySystem deliverySystem = (from, destinations, body) -> { // looks up MX records, connects to external SMTP servers and relays the message }; DataTransferState(String from, List<String> destinations) { this.from = from; this.destinations = destinations; } @Override public String handleCommand(String command, SMTPSessionHandler context) { if (command.equals(".")) { deliverySystem.deliver(from, destinations, body.toString()); context.setCurrentState(new InitialState()); return "250 Ok: the email has been delivered"; } else { body.append(command); body.append('n'); return null; } } } 8 Implementing an SMTP server with the State Pattern (4/4)
  • 9. Conclusion: benefits of the State Pattern • Concise and short classes with clear responsibility • Clear state transition • Better maintainability • You can write a new concrete state class for a new state • There will be no giant classes 9