Factory method mode and abstract Factory mode
Simple Factory mode
The usual methods are static, so they are also called static factories.
Although a simple factory can be created in theory, it is generally not too large for a simple factory to create objects, and it is recommended to control it at a separate component level or at a module level, where a component or module corresponds to a simple factory
The class name is suggested as "module name +factory", such as "userfacory"; The method name is usually "get+ interface name" or "Create+ interface name", such as "Getuserbean"
public interface player{//athlete Interface Public viod run (); public void jump (); public class Footballplayer implements player{//soccer player Public Viod run () {//do something}; Public Viod jump () {//do something};} public class Basketballplayer implements player{//basketball player public Viod run () {//do something}; Public Viod jump () {//do something};} public class playerfactory{//Player factory class public static player get Footballplayer () {return new Footballplaye R (); public static Player Get Basketballplayer () {return new Basketballplayer (); }} public class test{//Football club (basketball club similar to this) private Player goalkeeper; Goalkeeper Private Player forward; Striker Private Player defender; Defender public void Clubtest () {this. goalkeeper = Playerfactory. Footballplayer (); This. Forward = Playerfactory. Footballplayer (); This. DeFender = Playerfactory. Footballplayer (); }}
The simple factory solves the confusion of exposing the specific class to the client without the interface, without the factory, the interface is used to encapsulate and isolate the concrete implementation, the goal is not to let the client know the concrete implementation of the encapsulation inside
The essential purpose of a simple factory is to select a suitable implementation class to use
Factory method Mode
The difference between a factory method pattern and a simple factory model is that the simple factory model has only one factory class, and the factory method pattern has a set of factory classes that implement the same interface
public interface player{//athlete Interface Public viod run (); public void jump (); public class Footballplayer implements player{//soccer player Public Viod run () {//do something}; Public Viod jump () {//do something};} public class Basketballplayer implements player{//basketball player public Viod run () {//do something}; Public Viod jump () {//do something};} public interface club{//Club Interface-Class-N-Player Register (), the publicly class Footballclub implements club{//football Club specific work Factory type Public Player register () {return new Footballplayer (); };} public class Basketballclub implements club{//basketball Club specific factory-class public Player register () {return new BASKETBA Llplayer (); };} public class test{//Football club (basketball club similar to this) private Player goalkeeper; Goalkeeper Private Player forward; Striker Private Player defender; Defender's Club = new Footballclub (); public void ClubtesT () {this. goalkeeper = Club.register (); This. Forward = Club Register (); This. Defender = Club Register (); }}
Abstract Factory mode
The biggest difference between the abstract factory pattern and the factory method pattern is the complexity of creating objects, the factory method pattern is for a product hierarchy, and the abstract factory pattern faces multiple product hierarchies
The purpose of the abstract factory is to provide the client with an interface that can create product objects in multiple product families, and the following conditions are also met with abstract factories:
1, the system has a number of product families, and the system can only consume one family of products at a time;
2. Use with products belonging to the same product family
In the following example, the football team soccer player and football coach is a product family, similarly, the same basketball team. Football coaches can't train basketball teams, basketball coaches can't train football teams, they're tied to the category of athletes.
public interface player{//athlete Interface Public viod run (); public void jump (); public class Footballplayer implements player{//soccer player Public Viod run () {//do something}; Public Viod jump () {//do something};} public class Basketballplayer implements player{//basketball player public Viod run () {//do something}; Public Viod jump () {//do something};} Pubic interface coach{//coach Interface public void Train (), public class Footballcoach implements coach{/soccer coach Publi c void Train () {//soccer coach leads soccer player training}; public class Footballcoach implements coach{//basketball coach public void Train () {//basketball coach leading basketball player training}; public Interface abstractclubfactory{//Club's abstract factory public Coach Createcoach (); Hire coach Public Player Createplayer (); Recruit athlete} public class Footballfactory implements abstractclubfactory{//soccer team factory public Coach Createcoach () {//Hire football coach return new Footballcoach (); }; Public Player Createplayer () {//Recruit football operator return new Footballplayer (); };} public class Footballfactoryimplements abstractclubfactory{//basketball team factory public coach Createcoach () {//hire a basketball coach return new Footballcoach (); }; Public Player Createplayer () {//Recruit basketball operator return new Footballplayer (); };} public class test{//test class private coach coach; Private player player; public void Createclub (abstractclubfactoryfactory) {coach = factory. Createcoach (); Player = Factory. Createplayer (); }}
In the test class, the Createclub (Abstractclubfactoryfactory) method takes a class that implements the Abstractclubfactory interface as a parameter, and then it can create the corresponding team. If you pass in a footballfactory, you will create a football coach and a football player, and if you are footballfactory, you will create a basketball player and a basketball coach.
If you want to add a product family-volleyball team, also need coaches and athletes, need to consider from three places, the first need to add a player interface to implement the volleyball runner class, and then need to add a coach interface to implement the volleyball coach class, Finally, we need a factory class that implements the Abstractclubfactory and can create volleyball coaches and volleyball players. It can be seen that the abstract factory supports the open and close principle, that is, when the demand is changed, it is implemented by adding code rather than altering the original code.
Single-Case mode
The singleton mode has the following characteristics:
1. There is only one instance of this class
2. The class creates an instance of itself, creating its own instance object inside the class
3. Expose this instance interface to the entire system
In the case of Singleton mode, regardless of the implementation, it is only concerned with the creation of class instances, and does not care about the specific business logic
The singleton scope implemented in Java (that is, within what range is guaranteed to have only one instance) is a range of ClassLoader and its sub-classloader, if there are multiple ClassLoader in a virtual machine, and these classloader load this class , even if the class is a singleton pattern, it also produces multiple instances
The method named GetInstance is generally recommended for a singleton mode
The singleton pattern is divided into three types: lazy one-case, a hungry man-type single case and registration single-case
Lazy Single-case
Also becomes lazy loading, does not create an instance when the class is loaded, it is created only when the instance is first requested, and is created only once
public class singleton{ private static Singleton uniqueinstance =null; Private Singleton () { //privatized construction method, external cannot be created directly } //Plus synchronized keyword, is to prevent multiple threads calling getinstance error in multi-threaded environment Public static Synchronized Singletongetinstance () { if (instance = = null) { instance = new Singleton (); } return instance; } }
A hungry man type single case
When the class is loaded, the unique instance has been created
public class singleton{ private static Singleton uniqueinstance =new Singleton (); You can add the final keyword to prevent external modification of private Singleton () { //privatized construction method, external cannot be created directly } public static Singleton GetInstance () { return instance; } }
Registration Single-CASE
public class singleton{ //register, used to hold all registered instances private static map<string,singleton>registry = new HashMap (); static{//class loads when adding an instance to the Register Singleton sing = new Singleton (); Registry.put (Sing.getclass (). GetName (), sing); } Protected Singleton () { //protected construction Method}/ / for registered direct removal; not registered, register first, then remove public static Singleton GetInstance (stringname) { if (name = = null) { name = "Singleton"; } if (registry.get (name) ==null) { try{ registry.put (name, (Singleton) class.froname (name). newinstance); } catch (Exception e) { e.printstacktrace (); } Returnregistry.get (name); } }
For example, in many places the system needs to use the contents of the configuration file, you can consider using singleton mode to save memory resources
public class AppConfig {private static AppConfig instance = Newappconfig (); Private AppConfig () {//Privatization construction Method Readconfig (); } public static AppConfig getinstance () {return instance; } private String Parametea; Private String Parameteb; Public String Getparametera () {return parametea; } public String Getparameterb () {return parameteb; } private void Readconfig () {Properties p = new Properties (); InputStream in = null; try{in =appconfig.class.getresourceasstream ("appconfig.properties"); P.load (in); This. Parametera = P.getproperty ("Parama"); This. Parameterb = P.getproperty ("Paramb"); }catch (IOException e) {e.printstacktrace (); }finally{try{in.close (); }catch (IOException e) {e.printstacktrace (); } } } }
Test Client
AppConfig config= appconfig.getinstance (); String Parama = Config.getparametera (); String paramb =config.getparameterb ();
The following is a perfect code construct that allows for either single-mode thread-safe or lazy loading
public class singleton{ //inner class, an instance of this inner class has no binding relationship to an instance of an external class, and is loaded only when it is called, thus enabling lazy loading of the private static class singletonholder{ private static Singleton instance =new Singleton (); } Private Singleton () { //privatized construction method } public static Singleton getinstance () { return singletonholder.instance; } }
When the getinstance was first called, It first reads singletonholder.instance, causing the Singletonhoulder class to be initialized, and when the class is loaded and initialized, it initializes its static domain, and because it is a static domain, it is initialized only once by the virtual machine when the class is loaded, and the virtual machine guarantees its line Process Safety
Builder mode
There is a mentor role in the builder model, and the mentor is the one who manages the builders.
The builder model is designed to decouple design and construction from each other.
The same method, the different execution order, produces the different event result, may consider to adopt the builder pattern
The builder pattern is to encapsulate complex internal creation inside, and for external calls, simply pass in builders and build tools, and the caller does not need to care about how the interior is built to create the finished product.
If the factory model is seen as a car accessory manufacturing plant, producing different types of auto parts, then the builder model is a car assembly plant, which is assembled by assembling the parts to return a complete car
The factory model often cares only about what you want, doesn't care what the details of this thing are, and the builder pattern is concerned with the creation of the exact details of this thing.
public class car{//Car entity class private String head; Front private String body; Body private String tail; Tail//omitted setter, getter method} public abstract carbuilder{//assembly of automotive abstract class//assembled front public abstract void Makehead (); Assemble body public abstract void makebody (); Assemble trailer public abstract void Maketail (); Return the assembled car object public abstract car Getcar ();} public class Jeepbuilder extends carbuilder{//Jeep assembly class Car car = new car (); public void Makehead () {car.sethead ("Jeep Head"); }; public void Makebody () {car.sethead ("Jeep Body"); }; public void Maketail () {car.sethead ("Jeep Tail"); }; Public Car Getcar () {return car; };} Automotive Assembly Operations Encapsulation class public class Cardirector {//This class completes the design and determines which methods are executed and the order of execution public void Makecar (Carbuilder builder) { Builder.makehead (); Builder.makebody (); Builder.maketail (); }}
Test class
Cardirector director = new Cardirector (); Carbuilder builder = new Jeeprbuilder ();d Irector.makecar (builder); The builder of the Jeep is introduced into the conductor car car =builder.getcar (); Finally, the builder returns to the finished product
Imagine how the code should be changed if the process of producing a bus is to be added now?
First, create a new busbuilder that inherits the Carbuilder class, test the class, change the Jeeprbuilder to Busbuilder, and the rest without changing
Prototype mode
Prototype mode refers to the use of prototype instances to specify the types of objects created, and the creation of new objects by copying these prototypes
objects created by the copy method are completely new objects that have new addresses in memory
To implement the prototype pattern in the Java language:
public class Prototype implements cloneable {public Object clone () throws Clonenotsupportedexception { // Super.clone () is called by the Clone () method of object Prototype proto = (Prototype) super.clone (); return proto;
Test class
Prototype proto1= new Prototype (); Prototype proto2= Proto1.clone ();
There is a concept of shallow copy and deep copy when copying.
Shallow copy : After copying an object, the variables of the base data type are recreated, and the reference type, pointing to the original object. The base types include primitive types such as int, long, string, and none of the following two conditions will be copied: 1, the member variable of the class, not the variable within the method; 2, must be an object, not a basic type
deep copy : After copying an object, both the base data type and the reference type are recreated. In short, deep replication is completely replicated, and shallow copying is not exhaustive.
public class Thing implements cloneable{ private arraylist<string> arraylist= new arraylist<string> (); Public thing clone{ thing thing = null; try{ thing = (thing) supper.clone (); } catch (Clonenotsupportedexceptione) { //exception handling } return thing; } public void SetValue (String value) { this.arrayList.add (value); } Public arraylist<string> GetValue () { return ArrayList; } }
Test class
Thing Thing =new Thing (); Thing.setvalue ("Zhang San"); Thing clonething= Thing.clone (); Clonething.setvalue ("John Doe"); System.out.println (Thing.getvalue ());
The expected run result is "Zhang San", actually print out is "Zhang San, John Doe"
At this time because the above is a shallow copy, thing in the ArrayList did not copy a new object out, thing and clonething actually share the same ArrayList, you change, I change, we can change, is a very unsafe way
public class Prototype implements Cloneable, Serializable {private static final long serialversionuid= 1L; private string string; Private Serializableobject obj; /* Shallow copy */public Object clone () throws clonenotsupportedexception{Prototype proto = (Prototype) super.clone (); return proto; }/* Deep copy */public Object Deepclone () throwsioexception, classnotfoundexception {/* Write binary stream of current object */ Bytearrayoutputstream BOS = new Bytearrayoutputstream (); ObjectOutputStream oos = new ObjectOutputStream (BOS); Oos.writeobject (this); /* read out the new object generated by the binary stream */Bytearrayinputstream bis =new bytearrayinputstream (Bos.tobytearray ()); ObjectInputStream ois = Newobjectinputstream (bis); return Ois.readobject (); public string getString () {return string; The public void setString (string string) {this.string = string; } public Serializableobject Getobj () { return obj; } public void Setobj (Serializableobject obj) {this.obj = obj; }} class Serializableobject implements Serializable {private static final long serialversionuid= 1L;}
If you need to implement deep replication, such as serialization (serialization), and so on, serialization is the process of writing an object to a stream, the object written to the stream is a copy of the original object, and the original object still exists in memory
An object that can be serialized whose class must implement the Serializable interface