Rule of thumb: Consider a static factory method instead of a public construction method
First, the static factory method
For Java classes, in order for a consumer to get an instantiated object of its own, the following methods are available:
1. This class provides a public construction method. In this case, the program can create any number of instances of the class through multiple new construct method statements. However, each execution of a new statement results in a fresh object in the heap area of the Java Virtual machine.
2. This class provides a public static factory method (it is just a simple static method that returns an instance of a class that differs from the factory method pattern in design mode). For some Java platform Library classes or your own tool classes, parameterized classes, you need to further encapsulate the details of creating your own instances, and control the number of instances of your own, then you can use Method 2 to provide a static factory approach. For example, the class instance is created automatically when a Java virtual machine loads a class, and the program cannot create an instance of the Java.lang.Class class with the new statement because the class does not provide a construction method for the public type. In order for the program to obtain class instances representing a class, the static Factory method forname (String name) is provided in the class classes, as follows:
Class clazz=class.forname ("Firstdemo"); Returns an instance representing the Firstdemo class
Both the static factory method and the public construction method have their merits, but the static factory method is usually more appropriate, so the static factory method can be given precedence when used.
Note: Not all cases, the static factory method is better than the public construction Method! To fully understand the application of static factory methods, can grasp the way to be able to take advantage of this approach, otherwise it is best to use the Java Standard public construction method, to avoid program confusion.
Here is a detailed comparison of the differences between the two.
Ii. comparison of static plant methods and construction methods
In some cases, providing a static factory method instead of a public construction method has the following advantages :
1, each static factory method can have its own arbitrary definition of the name , so in the method name can reflect the information related to the instance, can improve the readability of the program code. In a class, the name of the constructor must be the same as the class name, even if you need to provide 2 construction methods, only the number of parameters of the constructor method is different or the number of the same, but the order of the parameter type is different, so it is not possible to distinguish the purpose of each overloaded method from the name alone, which can cause confusion. For example, using a static factory method to obtain male and female instances is clearly easier to read:
1 public class Gender {2 //Privatization instance and construction Method 3 Private String description; 4 private static final Gender female = NE W Gender ("female"); 5 private static final Gender male = new Gender ("male"); 6 Private Gender (String description) {7 This.descriptio n = description; 8 } 9 //public static factory method Gender getfemaleinstance () {//Get female instance one return female;12 }13 Public static Gender getmaleinstance () {//Get male instance return male;15 }16 public String GetDescription () { description;18 }19}
Note: The construction method is private if you replace the constructor method with a static factory method, but it is also possible if you want to also provide a public construction method.
2, as mentioned above using the new construction method to execute the new statement every time the instance is created, and the static factory method does not have to create a new object on each invocation, whether a new object will be created depends entirely on the implementation of the method.
1 public class Staticfactorydemo {2 private static final Staticfactorydemo demo = new Staticfactorydemo ();//private, Static, fin Al, construction method instantiation object 3 public static Staticfactorydemo getinstance () {//Common static factory method, get instantiated object 4 return demo;5 }6 public void Printmessage () {//Common Method 7 System.out.println ("Test Static Factory class!"); 8 }9}
For example, a custom getinstance () static method provides a return to an object in the global uniqueness object of the preceding code. If you need to call the Printmessage method in the Staticfactorydemo class in another class, you only need to use the following statement instead of using the New keyword:
Staticfactorydemo.getinstance (). Printmessage ();//Call Printmessage method
With this feature, the static factory method can be used to create instances of the following classes.
Singleton class: A class with only a unique instance (such as the Staticfactorydemo class above).
Enumeration classes: Classes with a limited number of instances (e.g., enum weekday{Sun,mou,tue,wed,thu,fri,sat};).
A class with an instance cache (which typically satisfies: 1, the number of instances of a class is limited to 2, a specific instance of the class is frequently accessed during program execution): A class that can store an instance that has already been created in a cache.
Immutable classes with an instance cache: Once an instance of an immutable class is created, its property values are not changed. Immutable class extension code with the instance cache:
1 Import java.lang.ref.SoftReference; 2 Import Java.util.HashSet; 3 Import Java.util.Iterator; 4 Import Java.util.Set; 5 6 public class name {7 private string FirstName; 8 private string LastName; 9 Private name (String Firstnam E, String lastname) {this.firstname = firstname;11 This.lastname = lastname;12}13//instance cache, storing NA Soft reference to the Me object in the private static final set<softreference<name>> names = new hashset<softreference<name>& gt; (); ValueOf static Factory Method-public static Name valueOf (string firstname, String lastname) {iterator< Softreference<name>> it = Names.iterator (); while (It.hasnext ()) {softreference<name& Gt ref = It.next (); Obtain a soft reference to the name of the name = Ref.get (); Get a soft reference to the name object referenced by the IF (name! = NULL && name.firstname.equals (firstname) && name.lastname.equ ALS (LastName)) return name;23}24//If n is not present in the cacheAme object, the object is created, and its soft reference is added to the instance cache at the same time. Name name = new name (firstname, LastName); Names.add (New SOFTREFERENCE&L T name> return name;28}29//Main method public static void main (string[] args) {-Name N1 = name.valueof ("Big", "Zhang"), the name N2 = name.valueof ("Big", "Zhang"), the name n3 = name.valueof ("small", "Li"); 34 SYSTEM.OUT.PRINTLN (N1), System.out.println (N2), System.out.println (N3), Panax Notoginseng System.out. println (n1 = = N2); Print True38}39}
Extensions < immutable classes: For example, all basic types of wrapper classes in the JDK base class library, such as the integer and long classes, are immutable classes and java.lang.String are immutable.
Create an immutable class:
1. All members are private
2. Do not provide methods for changing members, for example: SETXX
3. Ensure that all methods are not overloaded. There are two ways to do this: Use the final class (Strong immutable Class), or add all class methods to final (weakly immutable classes).
4. If a class member is not the original variable (boolean,byte, char, double, float, integer, long, short) or immutable class, it must pass through the deep clone method when the member is initialized or the Get method, To ensure that the class is immutable. For example:
1 Public final class Finalclass {//Immutable Class 2 private final int[] iarray;//private member variable 3 public finalclass (int[] Aarra Y) {//int array is not the original variable, need to use depth Clone method, guarantee class immutable 4 This.iarray = Aarray.clone (); 5 } 6 public String toString () {7 stringbuffer sb = new StringBuffer ("Numbers is:"); 8 for (int i = 0; i < iarray.length; i++) {9 sb.append (Iarray[i] + ""); }11 return sb.tostring (); 12 }13}
3. The new construction method can only create an instance of the current class, whereas a static factory method may return an instantiated object of any subclass of the current class.
3.1 When using a static factory method, the caller is required to refer to the returned object through an interface , rather than by implementing a class to refer to the returned object. For example, vectors and ArrayList are implementations of the list interface:
list<string> sStrings1 = new vector<string> (); list<string> sStrings2 = new arraylist<string> ();
3.2 The Static factory method returns the class to which the object belongs, can be non-public, or can change with each invocation, and it can be unnecessary to write a class that contains the static factory method.
3.3 This feature can play a role in creating loosely coupled system interfaces.
Extension: The Static factory approach forms the basis for the service provider framework. The service provider framework refers to the implementation of a service by multiple service providers, which provide multiple implementations of the service provider's clients and decouple them from multiple implementations. Includes 4 components: Service interface, provider registration API, service access API (core base), service Provider Interface (optional). For example, code:
1/* Service Provider Framework Description */2//Service Interface 3 public interface Service {4//... 5} 6 7//Service Provider Interface 8 public interface Provider {9 service NewService (),}11 public class Services {Priva Te Services () {}15 private static final map<string, provider> providers = new concurrenthashmap<string , provider> ();//Storage service provider information for public static final String default_provider_name = "<def>"; 17//Provider Registration API18 public static void Registerdefaultprovider (Provider p) {//default registry service provider Registerprovider (Default_provider_name, p );}21 public static void Registerprovider (String name, Provider p) {//Registered service provider: providers.put (name, p); 23}24//service access API (using static Factory method, return value is interface type) public static service newinstance () {//Default instantiation service-return Newinst Ance (default_provider_name);}28 public static service newinstance (String NAME) {//instantiation service PROVIDER p = Providers.get (name); if (p = = null)//If no registered service provider exists, no service is available 31 throw new IllegalArgumentException ("No provider registered with Name:" + name), return P.newservice (),//if present Registered service provider, NewService () can provide services 33}34}
4, static Factory method, when creating a parameterized type instance, you can be concise code.
Assuming that a parameterized construction method is called, it typically takes two times to indicate the type of the parameter, such as:
map<string,list<string>> m = new hashmap<string,list<string>> ();
Assume that HashMap provides the following static factory methods:
public static <K,V> hashmap<k,v> newinstance () {return new hashmap<k,v> ();}
At this point, you can instantiate the object using the static factory method above:
map<string,list<string>> m = hashmap.newinstance ();
However, there are drawbacks to using static factory methods:
1. If the class does not contain public or protected construction methods, it cannot be quilt-like (inherited). Also, non-public classes returned for static factory methods cannot be inherited. But programmers are often encouraged to use compositing instead of using inheritance.
2, it is not any different from other static methods. If there are many static factory methods in the system, it is not easy to know how to instantiate a class. It is therefore required that programmers use static factory methods with detailed explanatory notes and follow standard naming conventions. The usual names are as follows:
ValueOf (usually type conversion method); getinstance (get instance); Newinstance (create instance); Gettype;newtype ...
Rule of thumb: Consider a static factory method instead of a public construction method