Compare the state pattern and the policy pattern in Java design pattern programming

  • 2020-05-09 18:39:19
  • OfStack

In order to properly use the state and policy patterns in Java applications, developers need to be aware of the differences between the two. Although the structure of the state pattern and the policy pattern are very similar, they both follow the open and closed principle and represent the 'O' of the SOLID design principle, their intentions are completely different. The policy pattern in Java encapsulates a set of related algorithms, giving callers runtime flexibility. Callers can select a different algorithm at run time without modifying the Context class that USES the policy. Classic examples of using the policy pattern include implementing encryption algorithms, compression algorithms, and sorting algorithms. On the other hand, the state mode can use an object to show different behaviors in different states. Objects in the real world are stateful, and they will behave differently depending on the state. For example, a vending machine can only sell items in the hasCoin state. If you don't put COINS in it, it won't sell. Now you can clearly see the difference between the policy pattern and the state pattern, and their purposes are different. The state pattern helps the object manage its state, while the policy pattern allows the client to choose different behaviors. One less obvious difference is who drives behavior change. In the policy pattern, it is client-driven, which provides different policies for context information, while in the state pattern, the migration of states is managed by the Context or State objects themselves. Similarly, if you make state changes in the State object, it must hold a reference to Context, which means that for the vending machine, it can call the setState method to modify the current state of Context. On the other hand, the policy object does not hold a reference to Context; its client passes the selected policy to Context. The strategy mode and the state mode are the most common interview questions about the Java design pattern, which we will cover in detail in this article on the Java design pattern. We will explore the similarities and differences between the two models, which will help improve your understanding of them.

Similarities between the state mode and the policy mode:
If you look at the UML diagram for the policy pattern and the state pattern, they look very similar. In state mode, objects that use State objects to change behavior are called Context objects, and similarly in policy mode, objects that use Strategy objects to change behavior are also Context objects. Remember, the client interacts with the Context object. In the state mode, Context proxies method calls to the state object, the current object in Context is the concrete state object, and in the policy mode, Context operates on the policy object, which is either passed in as a parameter or provided when the Context object is created.

Let's look at some similarities between the two core Java design patterns:

Both the state pattern and the policy pattern make it easy to add new states or policies without affecting the Context objects that use them
Both patterns follow an open and closed design principle, which means that your design is open for extension and closed for modification. In both modes, Context is closed to modification, adding states or policies so that you don't need to modify Context objects in other states, or make minor changes
Just as Context objects in state mode have an initial state of 1, Context in policy mode usually has a default policy.
State patterns encapsulate different behaviors in the way of different state objects, while policy patterns encapsulate different behaviors in the way of different policy objects.
Both patterns rely on concrete subclasses to implement concrete behavior. Each concrete policy extends from an abstract policy class, and each state is an interface or subclass of an abstract class that represents the state.


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() { 
    /* 
     *  You do different things in different states,   Reswitch state  
     */ 
    if (" window ".equals(stateValue)) { 
      switchWindow(); 
      this.stateValue = " Full screen "; 
    } else if (" Full screen ".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 "); 
  } 
   
} 

/** 
 *  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) model   Behavioral pattern  
 *  It changes both the state of the object and its behavior  
 *  Change your behavior based on your state  
 */ 
public class Test { 
  public static void main(String[] args) { 
    /* 
     *  In this case the   There are only two state values, which are controlled by the state class itself  
     *  The control of the state value can also be left to the client to set  
     */ 
    WindowContext context = new WindowContext(new WindowState(" window ")); 
    context.switchState(); 
    context.switchState(); 
    context.switchState(); 
    context.switchState(); 
 
  } 
} 

print


 Switch to window state  
 Switch to full screen  
 Switch to window state  
 Switch to full screen  


Policy pattern example


/** 
 *  Commodity sales promotion  
 *  This class is: the class that receives cash  
 */ 
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; 
  } 
 
} 


/** 
 *  Discounted cash  
 * @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(); 
  } 
   
   
} 



/** 
 *  Benefit cashback   cash  
 * @author stone 
 * 
 */ 
public class CashReturn implements ICashSuper { 
  private double moneyCondition; // The minimum amount of cash back  
  private double returnMoney; // The 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; 
    } 
  } 
   
   
} 


/** 
 *  According to the passed policy class, perform the corresponding behavior  
 */ 
public class CashContext { 
  private ICashSuper casher; 
   
  public CashContext() { 
     
  } 
   
  public CashContext(ICashSuper casher) { 
    this.casher = casher; 
  } 
   
  public void setCasher(ICashSuper casher) { 
    this.casher = casher; 
  } 
   
  // Depending on the specific policy object, its algorithmic behavior is called  
  public double acceptCash(double money) { 
    return this.casher.acceptCash(money); 
  } 
   
} 


public class Test { 
  public static void main(String[] args) { 
    double money = 998; // The original price  
    CashContext cashContext = new CashContext(new CashNormal()); 
    System.out.println(" The original price: " + cashContext.acceptCash(money)); // usually   strategy  
     
    cashContext.setCasher(new CashRebate(8.5)); 
    System.out.println(" play 85 Fold: " + cashContext.acceptCash(money)); // discount    strategy   85 fold  
     
    cashContext.setCasher(new CashReturn(300, 50)); 
    System.out.println(" full 300  return 50 : " + cashContext.acceptCash(money)); // Cash back   strategy    full 300  return 50 
     
  } 
} 

print


/** 
 *  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(); 
  } 
} 

0

The difference between a policy pattern and a state pattern
We have seen that the two patterns are structurally very similar, but there are still differences. Here are some key differences between them.

The policy pattern encapsulates a series 1 of related algorithms that use clients to combine and delegate different behaviors at run time, while the state pattern enables objects to exhibit different behaviors in different states. Another difference between the two patterns is that the state pattern encapsulates the state of the object, while the policy pattern encapsulates an algorithm or policy. Because the state is coupled to the object at 1, it cannot be reused, but it can be reused by policies or algorithms independent of its context. In the state pattern, the state itself contains a reference to Context for state migration, but the policy pattern does not have a reference to Context Specific policies can be passed as one argument to the object using them, such as Collections.sort (), which accepts one Comparator, which is one policy. In addition, the state itself is part 1 of the Context object. As time goes by, the Context object will migrate from one state to another. Although both patterns follow the open closed principle, the policy pattern also follows the single 1 responsibility principle, because each policy encapsulates an independent algorithm, and the different policies are independent of the others. Changing one policy does not affect the implementation of the other. In theory, there is a different pattern, strategy pattern and status of the definition of the former is an object "how" to do one thing, for example how to sort the data, and the other 1, state model is defined by the "what" and "when", for example, an object can do, some point which state it is in. The order in which states are migrated is defined in the state pattern, but not in the policy pattern. The client can choose which policy to use at will. Common examples of policy patterns are encapsulation algorithms, such as sorting algorithms, encryption algorithms, or compression algorithms. If you find that you need to use different algorithms in your code, consider using the policy pattern. If you need to manage states to migrate between states, and you don't want to nest a lot of conditional statements, then state mode is your first choice because it's very simple. The last and most important difference is that the policy pattern is handled by the client, whereas the state change can be done by either the Context or State objects.

This is all about the difference between the policy pattern and the state pattern in Java. As I said, they look very similar in the UML diagram, both following the open close principle and encapsulating behavior. The policy pattern is used to encapsulate algorithms or policies that are provided to the Context object at runtime as parameters or composite objects, while the state pattern is used to manage state migration.


Related articles: