Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

  • 23 design modes for shorthand
  • The singleton pattern
  • Factory Method pattern
  • Abstract Factory pattern
  • The Builder/Builder pattern
  • Prototype mode
  • Flyweight mode
  • The facade pattern
  • Adapter mode
  • Decorator pattern
  • Observer mode
  • Strategy mode
  • Bridge mode
  • The Template Method pattern
  • The Chain of Responsibility model
  • Composite mode
  • Proxy mode
  • Memento mode
  • Command mode
  • Updates continue at……

Here are 23 design patterns to memorize quicklyThe state patternRelated content.

The schema definition

For stateful objects, complex “judgment logic” is extracted into different state objects, allowing state objects to change their behavior when their internal state changes.

The state pattern wraps the behavior of objects changed by the environment into different state objects. The intention is to make the behavior of an object change when its internal state changes. Now let’s analyze its basic structure and implementation method.

The template implementation is as follows:

package com.niuh.designpattern.state.v1;

/** * 

* State mode *

*/
public class StatePattern { public static void main(String[] args) { // Create environment Context context = new Context(); // Process the requestcontext.Handle(); context.Handle(); context.Handle(); context.Handle(); }}// Abstract state class abstract class State { public abstract void Handle(Context context); } // The specific state is class A class ConcreteStateA extends State { public void Handle(Context context) { System.out.println("The current state is A."); context.setState(newConcreteStateB()); }}// The specific state is class B class ConcreteStateB extends State { public void Handle(Context context) { System.out.println("The current state is B."); context.setState(newConcreteStateA()); }}/ / environment class Context { private State state; // Define the initial state of the environment class public Context(a) { this.state = new ConcreteStateA(); } // Set the new state public void setState(State state) { this.state = state; } // Read the state public State getState(a) { return (state); } // Process the request public void Handle(a) { state.Handle(this); }}Copy the code

The following output is displayed:

The current status is a. The current status is B. The current status is a. The current status is B.Copy the code

Problem solved

The behavior of an object depends on its state (properties) and can change its related behavior as its state changes.

Patterns of

To compose (a role). role
Context role Also known as a context, it defines the interface of interest to the customer, maintains a current state, and delegates state-related operations to the current state object.
Abstract the State role Defines an interface that encapsulates the behavior of a particular state in an environment object.
Concrete State role Implement the behavior corresponding to the abstract state.

Example is given to illustrate

Instance profiles

Use “state mode” to design a multithreaded state conversion program.

Analysis of the: There are five states in multi-threading, namely, new state, ready state, running state, blocked state and dead state. Each state will be converted to other states when related method call or event is triggered. The state transformation rule is as follows:

Now define an abstract state class (TheadState), and then design a concrete state class for each of the above states: New, Runnable, Running, Blocked, and Dead. Each state has a method that triggers its state transition. The ThreadContext class creates an initial state (New) and provides the related trigger method. The following diagram shows the structure of the thread state transition program:

Using the step

Step 1: Define the abstract state class: thread state

abstract class ThreadState {
    / / state name
    protected String stateName;
}
Copy the code

Step 2: Define a concrete state class

// State class: new state
class New extends ThreadState {
    public New(a) {
        stateName = "New State";
        System.out.println("Current thread is in: New state.");
    }

    public void start(ThreadContext hj) {
        System.out.print("Call the start() method -->);
        if (stateName.equals("New State")) {
            hj.setState(new Runnable());
        } else {
            System.out.println("The current thread is not new and cannot call the start() method."); }}}// State class: ready state
class Runnable extends ThreadState {
    public Runnable(a) {
        stateName = "Ready state";
        System.out.println("The current thread is in: ready state.");
    }

    public void getCPU(ThreadContext hj) {
        System.out.print("Get CPU time -->");
        if (stateName.equals("Ready state")) {
            hj.setState(new Running());
        } else {
            System.out.println("Current thread is not ready and cannot fetch CPU."); }}}// Specific status class: running status
class Running extends ThreadState {
    public Running(a) {
        stateName = "Operating status";
        System.out.println("The current thread is in: running state.");
    }

    public void suspend(ThreadContext hj) {
        System.out.print(Call the suspend() method -->);
        if (stateName.equals("Operating status")) {
            hj.setState(new Blocked());
        } else {
            System.out.println("The current thread is not running and cannot call the suspend() method."); }}public void stop(ThreadContext hj) {
        System.out.print("Call stop() -->");
        if (stateName.equals("Operating status")) {
            hj.setState(new Dead());
        } else {
            System.out.println("The current thread is not running and cannot call the stop() method."); }}}// Concrete state class: block state
class Blocked extends ThreadState {
    public Blocked(a) {
        stateName = "Blocked state";
        System.out.println("The current thread is in: blocked state.");
    }

    public void resume(ThreadContext hj) {
        System.out.print(Call the resume() method -->);
        if (stateName.equals("Blocked state")) {
            hj.setState(new Runnable());
        } else {
            System.out.println("The current thread is not blocked and cannot call resume()."); }}}// Specific status: Death status
class Dead extends ThreadState {
    public Dead(a) {
        stateName = "State of death.";
        System.out.println("Current thread is in: dead state."); }}Copy the code

Step 3: Define the environment class

class ThreadContext {
    private ThreadState state;

    ThreadContext() {
        state = new New();
    }

    public void setState(ThreadState state) {
        this.state = state;
    }

    public ThreadState getState(a) {
        return state;
    }

    public void start(a) {
        ((New) state).start(this);
    }

    public void getCPU(a) {
        ((Runnable) state).getCPU(this);
    }

    public void suspend(a) {
        ((Running) state).suspend(this);
    }

    public void stop(a) {
        ((Running) state).stop(this);
    }

    public void resume(a) {
        ((Blocked) state).resume(this); }}Copy the code

The output

The current thread is in: New state. Call the start() method --> The current thread is in: ready state. Get CPU time --> Current thread in: running state. Call the suspend() method --> The current thread is: blocked. Call resume() --> The current thread is in the: ready state. Get CPU time --> Current thread in: running state. Call the stop() method --> The current thread is: dead.Copy the code

advantages

  1. The state pattern localizes the behaviors related to a specific state into one state and separates the behaviors of different states to satisfy the “single responsibility principle”.
  2. Reduce interdependencies between objects. Introducing different states into separate objects makes state transitions more explicit and reduces the interdependence of objects.
  3. Facilitate the expansion of the program. You can easily add new states and transitions by defining new subclasses.

disadvantages

  1. The use of state patterns inevitably increases the number of classes and objects in the system.
  2. The structure and implementation of state pattern are complicated, if used improperly, it will lead to confusion of program structure and code.

Application scenarios

State patterns are usually considered in the following situations.

  • Consider using state patterns when an object’s behavior depends on its state and it must change its behavior based on state at run time.
  • An operation has a large branch structure, and these branches depend on the state of the object.

Extension of state patterns

In some cases, there may be multiple environment objects that need to share a set of state. In this case, we need to introduce the share mode, which puts these specific state objects in the collection for the program to share. Its structure is shown as follows:

Analysis: The difference between the shared state mode is that a HashMap is added to the environment class to store related states, which can be retrieved when a state is needed. The program code is as follows:

package com.niuh.designpattern.state.v3;

import java.util.HashMap;

/** * 

* Share state mode *

*/
public class FlyweightStatePattern { public static void main(String[] args) { // Create environment ShareContext context = new ShareContext(); // Process the requestcontext.Handle(); context.Handle(); context.Handle(); context.Handle(); }}// Abstract state class abstract class ShareState { public abstract void Handle(ShareContext context); } // Specify state 1 class class ConcreteState1 extends ShareState { public void Handle(ShareContext context) { System.out.println("The current state is: State 1"); context.setState(context.getState("2")); }}// Specify state 2 class ConcreteState2 extends ShareState { public void Handle(ShareContext context) { System.out.println("The current state is: State 2"); context.setState(context.getState("1")); }}/ / environment class ShareContext { private ShareState state; private HashMap<String, ShareState> stateSet = new HashMap<String, ShareState>(); public ShareContext(a) { state = new ConcreteState1(); stateSet.put("1", state); state = new ConcreteState2(); stateSet.put("2", state); state = getState("1"); } // Set the new state public void setState(ShareState state) { this.state = state; } // Read the state public ShareState getState(String key) { ShareState s = (ShareState) stateSet.get(key); return s; } // Process the request public void Handle(a) { state.Handle(this); }}Copy the code

The output is as follows

The current status is:1The current status is:2The current status is:1The current status is:2
Copy the code

Application in source code

# state pattern in the JDK: Java. Util. # Iterator by FacesServlet control, behavior depends on the current of the JSF lifecycle stage, state javax.mail. Faces. Lifecycle. LifeCycle# the execute ()Copy the code

PS: The above code is submitted to Github: github.com/Niuh-Study/…

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy