In order to correctly use state and policy patterns in Java applications, developers need to know clearly the difference between the two patterns. Although the structure of state modes and policy modes are very similar, they also follow the principle of opening and closing, representing the 'O' of the SOLID design principle, their intentions are completely different. The policy pattern in Java is to encapsulate a set of related algorithms, providing callers with runtime flexibility. The caller can choose different algorithms at runtime without modifying the Context class using the policy. Classic examples of using policy patterns include implementation of encryption algorithms, compression algorithms, and sorting algorithms. On the other hand, state mode uses an object to show different behaviors in different states. Objects in the real world also have states, and they will behave differently according to their states. For example, a vending machine can only sell items in hasCoin state. If you don't stuff coins in, it will not sell goods. Now you can clearly see the difference between policy mode and state mode, their purpose is different. State mode helps an object manage its state, while policy mode allows clients to choose different behaviors. Another difference that is not easy to see is who drives behavior changes. In the policy mode, it is client-driven, which provides different policies for context information. In the state mode, state migration is managed by the Context or State object itself. Similarly, if you modify the state in the State object, it must hold a reference to the Context, which means that for the vending machine, it can call the setState method to modify the current Context state. On the other hand, the policy object does not hold a reference to the Context, and its client passes the selected policy to the Context. Strategy and state patterns are the easiest interview questions about Java design patterns. In this article about Java design patterns, we will introduce this in detail. We will explore the similarities and differences between the two modes, which will help improve your understanding of the two modes.
Similarities between state mode and policy mode:
If you look at the UML graphs of policy patterns and state patterns, they look very similar. In state mode, the object that uses the State object to change behavior is called a Context object. Similarly, in strategy mode, the object that uses the Strategy object to change behavior is also a Context object. Remember, the client interacts with the Context object. In state mode, Context proxys the method call of the state object. The current object in Context is the specific state object. In policy mode, Context operates also the policy object. This object is either passed in as a parameter or is provided when creating the Context object.
Let's take a look at some similarities between these two core Java design patterns:
Both state mode and policy mode are easy to add new states or policies without affecting the use of them both follow the design principle of opening and closing, that is, your design is open to extensions and closed to modifications. In these two modes, Context is closed for modification, and adds a new state or a policy. You do not need to modify the Context object in other states, or only require small changes. Just as the Context object in the state mode will have an initial state, Context in the policy mode usually also has a default policy.
The state mode encapsulates different behaviors in the way of different state objects, while the policy mode encapsulates different behaviors in the way of different policy objects.
Both patterns rely on specific subclasses to achieve specific behavior. Each specific policy extends from an abstract policy class, and each state is also an interface used to represent states or a subclass of the abstract class.
State Mode Instance
public class WindowState { private String stateValue; public WindowState(String stateValue) { this.stateValue = stateValue; } public String getStateValue() { return stateValue; } public void setStateValue(String stateValue) { this.stateValue = stateValue; } public void handle() { /* * Do different operations according to different states, and then switch state*/ if ("Window".equals(stateValue)) { switchWindow(); this.stateValue = "full screen"; } else if ("Fullscreen".equals(stateValue)) { switchFullscreen(); this.stateValue = "Window"; } } private void switchWindow() { System.out.println("Switch to window state"); } private void switchFullscreen() { System.out.println("Switch to full screen state"); } } /** * Use of state*/ public class WindowContext { private WindowState state; public WindowContext(WindowState state) { this.state = state; } public WindowState getState() { return state; } public void setState(WindowState state) { this.state = state; } public void switchState() { this.state.handle(); } } /* * State (State) mode behavioral mode* Changes both the state of the object and the behavior of the object* According to the state, change the behavior*/ public class Test { public static void main(String[] args) { /* * There are only two state values in this example, which are controlled by the state class itself* You can also control the state value and hand over the client to set */ WindowContext context = new WindowContext(new WindowState("Window")); context.switchState(); context.switchState(); context.switchState(); context.switchState(); context.switchState(); context.switchState(); } }Switch to window state to full screen state to window state to full screen state
Policy Mode Example
/** * Product promotion* This category is: Cash collection*/ public interface ICashSuper { double acceptCash(double money); } /** * Normal cash collection* @author stone * */ public class CashNormal implements ICashSuper { @Override public double acceptCash(double money) { return money; } } /** * Cash is collected at discounts* @author stone * */ public class CashRebate implements ICashSuper { private double rebate; //Discount public CashRebate (double rebate) { this.rebate = rebate; } @Override public double acceptCash(double money) { return new BigDecimal(money * rebate / 10).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); } } /** * Cash rebate with cash* @author stone * */ public class CashReturn implements ICashSuper { private double moneyCondition; //Cashback minimum amount private double returnMoney; //Return amount public CashReturn(double moneyCondition, double returnMoney) { this.moneyCondition = moneyCondition; this.returnMoney = returnMoney; } @Override public double acceptCash(double money) {//Multiple rebate if (money >= moneyCondition) { return money - Math.floor(money / moneyCondition) * returnMoney; } else { return money; } } } /** * Execute the corresponding behavior based on the passed policy class*/ public class CashContext { private ICashSuper casher; public CashContext() { } public CashContext(ICashSuper casher) { this.casher = casher; } public void setCasher(ICashSuper casher) { this.casher = casher; } //According to the specific policy object, the algorithm behavior of calling it public double acceptCash(double money) { return this.casher.acceptCash(money); } } public class Test { public static void main(String[] args) { double money = 998; //Original price CashContext cashContext = new CashContext(new CashNormal()); System.out.println("Original price:" + cashContext.acceptCash(money)); //General strategy cashContext.setCasher(new CashRebate(8.5)); System.out.println("85% off:" + cashContext.acceptCash(money)); //Discount strategy 85% off cashContext.setCasher(new CashReturn(300, 50)); System.out.println("Return 50 if over 300:" + cashContext.acceptCash(money)); //Cashback strategy 50 if over 300} }Original price: 998.0 85% off: 848.3 Rebate for 50: 848.0 over 300
The difference between policy mode and state mode
We have learned that the two patterns are very similar in structure, but they still have different parts. Let’s take a look at some of the key differences between them.
This is all the differences between policy patterns and state patterns in Java. As I said, they look very similar in UML diagrams, both follow the principle of opening and closing and encapsulating behavior. The policy mode is used to encapsulate algorithms or policies. It will be provided to the Context object as a parameter or combination object at runtime, while the state mode is used to manage state migration.