The state of an object no longer changes after the object is created, which is known as the invariant pattern.
Structure of the invariant pattern
The invariant mode enhances the robustness of the object (robustness). The invariant mode allows multiple objects to share an object, reducing the synchronization overhead when concurrent access is made to the object. If you need to modify the state of an immutable object, you need to create a new object of the same type and store the new state in the new object when it is created.
The invariant pattern involves only a single class. When the internal state of a class is created, this class is called an immutable class when the entire life cycle is not changed. The practice of using immutable classes is called invariant mode. There are two forms of invariant mode: one is the weakly invariant mode and the other is the strong invariant mode.
Weakly invariant mode
The state of an instance of a class is immutable, but instances of subclasses of this class have states that may change. Such classes conform to the definition of a weakly invariant pattern. To implement a weakly invariant pattern, a class must meet the following criteria:
First, the object being considered has no method to modify the state of the object, so that when the object's constructor initializes the state of the object, the state of the object is no longer changed.
Second, all attributes should be private. Do not declare any of the exposed properties in case the client object modifies any internal state directly.
Third, how other objects referenced by this object are mutable objects must try to restrict access to these mutable objects to prevent the outside world from modifying those objects. How possible, you should try to initialize these referenced objects inside immutable objects, instead of initializing them in the client and then passing them inside the immutable object. If a mutable object must be initialized at the client and then passed into the immutable object, consider copying the mutable object to a copy of the immutable object when it is initialized, rather than using the original copy.
The disadvantages of the weakly invariant mode are:
The sub-object of the first to first weakly immutable object can be a mutable object, in other words, a child object of a weakly immutable object may be mutable.
Second, this mutable child object may be able to modify the state of the parent object, which may allow the outside world to modify the state of the parent object.
Strong invariant mode
An instance of a class does not change, and instances of its subclasses also have an immutable state. Such classes conform to the strong invariant pattern. To implement a strongly invariant pattern, a class must first meet all of the conditions required by the weakly invariant pattern, and also satisfy one of the following conditions:
First, all of the classes considered should be final, so that subclasses of this class cannot displace such methods.
Second, the class itself is final, then this class will not be able to have sub-class, so there is no way to have quilt class modification problem.
The difference between "invariant" and "read-only"
The "invariant" (immutable) is different from Read only. When a variable is "read-only", the value of the variable cannot be changed directly, but it can change when other variables change.
For example, a person's date of birth is a "constant" attribute, and a person's age is a "read only" attribute, not a "invariant" attribute. As time changes, the age of one person changes, and the person's date of birth does not change. This is the difference between "unchanging" and "read-only".
The application of invariant mode in Java
The most famous application of invariant mode in Java is the Java.lang.String class. The string class is a strongly invariant type when the following statement appears:
String a = "test"; String b = "Test"; String c = "Test";
A Java Virtual machine actually creates an instance of such a string, and these three string objects share this value.
The advantages and disadvantages of the invariant mode
The invariant mode has obvious advantages:
(1) Because you cannot modify the state of an immutable object, you can avoid unnecessary program errors caused by it; in other words, an immutable object is easier to maintain than a mutable object.
(2) because no one thread can modify the internal state of the immutable object, an immutable object is automatically thread-safe, which eliminates the overhead of processing synchronization. An immutable object can be freely shared with different clients.
Disadvantages of the invariant mode:
The only disadvantage of the invariant mode is that once you need to modify the state of an immutable object, you have to create a new homogeneous object. In an environment where immutable objects need to be modified frequently, a large number of immutable objects are created as intermediate results and then collected by the Java garbage collector. This is a waste of resources.
When designing any class, you should carefully consider whether the State has the possibility to change. Unless it is necessary to change its state, it should be designed as an immutable class.
The invariant mode of Java and pattern