Dynamic loading of the class with reflection
Bromon original, please respect the copyright
I recently wrote a mobile value-added project in Chengdu, and I was responsible for the background server. The function is very simple, and the mobile phone user opens the socket with the server via GPRS, and I respond according to the data passed by the user. Brothers who have done similar projects must know that first, a communication protocol similar to MSNP is needed, but today's topic is how to design this system highly scalable. Since this project itself did not have a relatively complete customer communication and demand analysis, there will be many functions in the future, and the communication agreement will definitely be more and more huge, and I as a less diligent person, of course, I don't want to go later. To modify the written program, this project is a good opportunity to practice object-oriented design.
First define an interface to isolate the class:
Package org.bromon.reflect;
Public Interface Operator
{
Public java.util.list act (java.util.list params)
}
According to the principle of design patterns, we can write different classes for different functions. Each class inherits the Operator interface, and the client only needs to program a lot of trouble for Operator interface. For example, this class:
Package org.bromon.reflect. *;
Public Class Success IMPLEments Operator
{
Public java.util.list act (java.util.list params)
{
List result = new arraylist ();
Result.Add (New String));
Return Result;
}
}
We can also write many other classes, but there is a problem, the interface cannot be instantiated, we must manually control which class, which is very unhappy, if you can pass a parameter to the application, let yourself choose to instantiate one Class, execute its ACT method, then our work is much easier.
Very lucky, I am using Java, only Java provides such reflex mechanisms, or the internal provincial mechanism, can achieve our unreasonable requirements. Write a configuration file Emp.properties:
# Successful response
1000 = SUCCESS
# Send a normal text message to customers
2000 = LOAD
# 客户 客户 Send a normal text message to the server
3000 = Store
The key name in the file is the message header that the customer will send it. The customer sends 1000 to me, then I will execute the ACT method of the Success class. If you send me 2000, then execute the ACT method of the Load class, so The system is fully compliant with the opening and closing principle. If you want to add a new function, you don't need to modify the existing code, just add the corresponding rules in the configuration file, then write new classes, implement the ACT method is OK, even if I abandon This project is going, it can also expand well in the future. Such systems have very good scalability and insertability.
The following example reflects the dynamic load function, and the program knows which class should be instantiated during the execution process:
Package org.bromon.reflect. *;
Import java.lang.reflect. *;
Public class testReflect
{
/ / Load the configuration file, query the class name corresponding to the message header
Private string loadProtocal (String Header)
{
String result = null;
Try
{
Properties Prop = New Properties ();
FileInputStream Fis = New FileInputStream ("Emp.Properties"); Prop.Load (FIS);
Result = prop.getProperty; Header;
fis.close ();
} catch (Exception E)
{
System.out.println (e);
}
Return Result;
}
// Response for messages, use reflection imported into the corresponding class
Public String Response (String Header, List Content)
{
String result = null;
String s = null;
Try
{
/ *
* Import Properties File Emp.properties, query the name of the class corresponding to Header
* Dynamically load matching class by reflective mechanism, all classes are isolated by Operator interface
* You can extend the protocol by modifying the properties file, add new classes (inherited MSGoperator interface)
* /
S = "org.bromon.reflect." this.loadProtocal (header);
// Load class
Class C = Class.Forname (s);
// Create a class
Operator mo = (operator) C.NewInstance ();
// Construct parameter list
Class params [] = new class [1];
Params [0] = Class.Forname ("java.util.list");
// Query ACT method
Method M = C.getMethod ("ACT", PARAMS);
Object args [] = new object [1];
Args [0] = Content;
// Call the method and get the return
Object returnObject = M.Invoke (Mo, Args);
} catch (Exception E)
{
System.out.println ("Handler-response:" E);
}
Return Result;
}
Public static void main (string args [])
{
TestReflect Tr = New Testreflect ();
Tr.Response (ARGS [0], "Message Content");
}
}
Test: Java TestReflect 1000
This program is for Operator programming, so there is no need to do any modifications, directly provide the LOAD and Store class, you can support the call of 2000, 3000 to do parameters.
With such an internal provincial mechanism, you can use the role of the interface to the extreme, and the design model can also reflect the power, not just after our meals.