Apenas necesito discutir por qué reutilizar el código es beneficioso. La reutilización del código generalmente hace que el desarrollo del programa sea más rápido y reduce los errores. Una vez que se encapsula y reutiliza un pedazo de código, es necesario verificar un código muy pequeño para garantizar la corrección del programa. Si solo necesita abrir y cerrar la conexión de la base de datos en un lugar durante toda la aplicación, es mucho más fácil asegurarse de que la conexión sea normal. Pero estoy seguro de que ya sabes todo esto.
Hay dos tipos de códigos de reutilización, que yo llamo tipos de reutilización:
El primer tipo es la reutilización funcional, que es el tipo de reutilización más común. Este también es un tipo de dominio para la mayoría de los desarrolladores. Es decir, reutilizar un conjunto de instrucciones posteriores para realizar alguna operación.
El segundo tipo es la reutilización del contexto, es decir, diferentes funciones u códigos de operación se encapsulan entre los mismos contextos, y el mismo contexto se encapsula como código de reutilización (el contexto aquí se refiere a una serie de las mismas instrucciones de operación). Aunque se está volviendo más popular en la inversión de control, no es común. Además, la reutilización del contexto no se describe explícitamente, por lo que el sistema no lo utiliza como la reutilización funcional. Espero que cambie después de leer este artículo.
Reutilización de funciones
La reutilización funcional es el tipo de reutilización más común. Es una reutilización de un conjunto de instrucciones que ejecutan algún tipo de operación. Los siguientes dos métodos son leer datos de la base de datos:
Lista pública ReadAlLUsers () {Connection Connection = NULL; Cadena sql = "seleccionar * de usuarios"; List users = new ArrayList (); intente {Connection = OpenConnection (); Declaración de preparación = Connection.PrepareStatement (SQL); ResultSet result = Declary.ExCuteQuery (); while (result.next ()) {// Reuse el usuario user = new User (); user.setName (result.getString ("nombre")); user.SetEmail (result.getString ("correo electrónico")); ussers.add (usuario); // Fin de código de reutilización} result.close (); declaración.close (); devolver usuarios; } catch (sqlexception e) {// ignorar por ahora} finalmente {// ignorar por ahora}} lista pública readusersOfStatus (status string) {Connection Connection = null; String sql = "Seleccionar * de usuarios donde status =?"; List users = new ArrayList (); intente {Connection = OpenConnection (); Declaración de preparación = Connection.PrepareStatement (SQL); Declary.setString (1, estado); ResultSet result = Declary.ExCuteQuery (); while (result.next ()) {// Reuse el usuario user = new User (); user.setName (result.getString ("nombre")); user.SetEmail (result.getString ("correo electrónico")); ussers.add (usuario); // Fin de código de reutilización} result.close (); declaración.close (); devolver usuarios; } catch (sqlexception e) {// ignorar por ahora} finalmente {// ignorar por ahora}}Para los desarrolladores experimentados, es posible descubrir el código reutilizable pronto. El lugar donde se comenta "código de reutilización" en el código anterior es el mismo, por lo que la reutilización puede ser encapsulada. Estas son las operaciones que leen registros de usuarios en instancias de usuario. Estas líneas de código pueden encapsularse en sus propios métodos, por ejemplo:
// Encapsula la misma operación en el método ReadUser Usuario privado Readuser (Resultado de resultados) lanza SQLException {user user = new User (); user.setName (result.getString ("nombre")); user.SetEmail (result.getString ("correo electrónico")); ussers.add (usuario); devolver el usuario; }Ahora, llame al método Readuser () en los dos métodos anteriores (el siguiente ejemplo muestra solo el primer método):
Lista pública ReadAlLUsers () {Connection Connection = NULL; Cadena sql = "seleccionar * de usuarios"; List users = new ArrayList (); intente {Connection = OpenConnection (); Declaración de preparación = Connection.PrepareStatement (SQL); ResultSet result = Declary.ExCuteQuery (); while (result.next ()) {users.Add (readuser (resultado))} result.close (); declaración.close (); devolver usuarios; } catch (sqlexception e) {// ignorar por ahora} finalmente {// ignorar por ahora}}El método Readuser () también se puede ocultar en su propia clase utilizando el modificador privado.
Lo anterior trata sobre la reutilización de funciones. La reutilización funcional es encapsular un conjunto de instrucciones que realizan operaciones específicas a través de métodos o clases para lograr el propósito de la reutilización.
Operaciones parametrizadas
A veces desea reutilizar un conjunto de operaciones, pero estas operaciones no son exactamente las mismas en cualquier lugar que use. Por ejemplo, los métodos readallusers () y readUsersOfStatus () abren una conexión, preparan una declaración, la ejecutan y recorren el conjunto de resultados. La única diferencia es que ReadusersOfStatus () requiere que se establezca un parámetro en preparación. Podemos encapsular todas las operaciones en un método ReaduserList (). Como se muestra a continuación:
Lista privada ReadUserList (String SQL, String [] Parámetros) {Conexión Conexión = NULL; List users = new ArrayList (); intente {Connection = OpenConnection (); Declaración de preparación = Connection.PrepareStatement (SQL); for (int i = 0; i <parameters.length; i ++) {Declary.setString (i, parámetros [i]); } Resultado resultado de resultado = Declary.ExCuteQuery (); while (result.next ()) {users.Add (readuser (resultado))} result.close (); declaración.close (); devolver usuarios; } catch (sqlexception e) {// ignorar por ahora} finalmente {// ignorar por ahora}} Ahora llamamos readUserList(...) de readAllUsers() y readUsersOfStatus() y damos diferentes parámetros de operación:
Lista pública readallusers () {return readUserList ("select * de usuarios", new String [] {});} public List ReadusersWithStatus (stating status) {return ReaduserList ("Seleccionar * de usuarios", nueva cadena [] {status});};};Creo que puede encontrar otras mejores formas de implementar funciones de reutilización y parametrizarlas para que sea más fácil de usar.
Reutilización de contexto
La reutilización de contexto es ligeramente diferente de la reutilización de características. La reutilización de contexto es la reutilización de una serie de instrucciones, y siempre se realizan varias operaciones entre estas instrucciones. En otras palabras, reutilice las declaraciones antes y después de varios comportamientos. Por lo tanto, la reutilización del contexto a menudo conduce a una inversión de clases de estilo de control. La reutilización del contexto es una forma muy efectiva de reutilizar el manejo de excepciones, la gestión del ciclo de vida de la conexión y la transacción, la iteración y el apagado del flujo, y muchos otros contextos operativos comunes.
Aquí hay dos métodos que se realizan con InputStream:
public void printStream (inputStream InputStream) lanza IOException {if (inputStream == null) return; IoException Exception = NULL; intente {int caracteres = inputStream.read (); while (personaje! = -1) {System.out.print ((char) carácter); // diferentes caracteres = inputStream.read (); }} finalmente {try {inputStream.close (); } catch (ioException e) {if (excepcion == null) lanzar e; }}} public String ReadStream (InputStream InputStream) lanza IOException {StringBuffer Buffer = new StringBuffer (); // diferente if (inputStream == null) return; IoException Exception = NULL; intente {int caracteres = inputStream.read (); while (personaje! = -1) {buffer.append ((char) carácter); // diferentes caracteres = inputStream.read (); } return buffer.ToString (); // diferente} finalmente {try {inputStream.close (); } catch (ioException e) {if (excepcion == null) lanzar e; }}}Los dos métodos son diferentes de la operación de flujo. Pero el contexto en torno a estas operaciones es el mismo. El código de contexto itera y cierra el InputStream. Además de las diferencias en el uso de marcas de comentarios, el código anterior es su código de contexto.
Como se muestra arriba, el contexto implica el manejo de excepciones y garantiza que la corriente esté cerrada correctamente después de la iteración. Escribir dicho código de manejo de errores y liberación de recursos una y otra vez es engorroso y propenso a errores. El manejo de errores y el manejo correcto de la conexión son más complejos en las transacciones JDBC. Obviamente, es más fácil escribir código una vez y reutilizarlo en cualquier lugar.
Afortunadamente, el método para encapsular el contexto es simple. Cree una clase de contexto y ponga el contexto público en ella. En el uso del contexto, se abstraen diferentes instrucciones de operación en la interfaz de operación, y luego cada operación se encapsula en la clase que implementa la interfaz de operación (llamada clase de operación aquí). Solo necesita insertar una instancia de la clase de operación en el contexto. Se puede hacer pasando una instancia de la clase de operación como parámetro para el constructor del objeto de contexto, o pasando una instancia de la clase de operación como parámetro al método de ejecución específico del contexto.
A continuación se muestra cómo separar el ejemplo anterior en el contexto y la interfaz operativa. StreamProcessor (interfaz de operación) se pasa como un parámetro para el método ProcessStream () de StreamProcessContext.
// Interfaz del complemento de procesamiento de flujo Interfaz de interfaz pública PROcessor {Public void Process (int input);} // Procesamiento de flujo de contexto Clase pública Clase PublicessCuessContext {// Instancia la interfaz de operación de Processor Stream y servir como un parámetro Public Void Processream (InputStream InputSeamprocessor Processor). IoException Exception = NULL; intente {int caracteres = inputStream.read (); while (carácter! = -1) {procesador.process (carácter); personaje = inputStream.Read (); }} finalmente {try {inputStream.close (); } catch (ioException e) {if (excepcion == null) lanzar e; Tirar excepción; }}}}Ahora puede usar la clase StreamProcessContext para imprimir el contenido de transmisión como el siguiente ejemplo:
FileInputStream inputStream = new FileInputStream ("myFile"); // Ejemplo de la operación a través de la implementación de subclase anónima de la interfaz streamprocessor new streamProcessContext (). Processstream (inputSteam, new StreamProcessor () {Public void Process (int input) {System.Print ((char) Enume);}});O lea el contenido de transmisión de entrada así y agréguelo a una secuencia de caracteres:
Public Class StreamToStringReader implementa StreamProcessor {private StringBuffer buffer = new StringBuffer (); public StringBuffer getBuffer () {return this.buffer; } Public void Process (int input) {this.buffer.append ((char) entrada); }} FileInputStream inputStream = new FileInputStream ("myFile"); streamToStringreader lector = new streamToStringReader (); new StreamProcessesContext (). Processstream (InputStream, Reader); // Do algo con entrada de stream.Reader.getBuffer ();Como puede ver, haga cualquier cosa con la transmisión insertando una implementación de interfaz de flujo de transmisión diferente. Una vez que el StreamProcessorContext se implementa por completo, nunca tendrá ningún problema con las transmisiones no cerradas.
La reutilización de contexto es muy poderosa y puede usarse en muchos otros entornos fuera del procesamiento de la corriente. Un caso de uso obvio es manejar las conexiones y las transacciones de la base de datos correctamente ( open - process - commit()/rollback() - close() ). Otros casos de uso son el procesamiento del canal de NIO y la sincronización de subprocesos en secciones críticas ( lock() - access shared resource - unlock() ). También puede convertir las excepciones verificadas de la API a excepciones sin control.
Cuando busque código adecuado para la reutilización de contexto en su proyecto, busque los siguientes modos de operación:
Cuando encuentra tal patrón, las operaciones regulares antes y después pueden lograr la reutilización del contexto.
Contexto como método de plantilla
A veces querrás tener múltiples puntos de complemento en el contexto. Si el contexto consta de muchos pasos más pequeños y desea que cada paso del contexto sea personalizable, puede implementar el contexto como un método de plantilla. El método de la plantilla es un patrón de diseño GOF. Básicamente, el método de plantilla divide un algoritmo o protocolo en una serie de pasos. Un método de plantilla generalmente se implementa como una clase base única y proporciona un método para cada paso en un algoritmo o protocolo. Para personalizar cualquier paso, simplemente cree una clase que extienda la clase base del método de plantilla y anule el método del paso que desea personalizar.
El siguiente ejemplo es un JDBCContext implementado como un método de plantilla. Las subclases pueden anular la apertura y el cierre de las conexiones para proporcionar un comportamiento personalizado. El método ProcessRecord (ResultSet de resultados) siempre debe anularse porque es abstracto. Este método proporciona operaciones que no están en el contexto y son diferentes en diferentes casos que usan JDBCContext. Este ejemplo no es un JDBCCContext perfecto. Solo se usa para demostrar cómo usar los métodos de plantilla al implementar el contexto.
public abstract Clase JDBCContext {DataSource dataSource = null; // El constructor sin parámetros se puede utilizar para subclases sin dataSource para obtener la conexión pública JDBCContext () {} public JDBCCContext (DataSource DataSource) {this.dataSource = DataSource; } Conexión protegida OpenConnection () lanza SQLException {return dataSource.getConnection (); } protegido void closeConnection (conexión de conexión) lanza SQLException {Connection.Close (); } // ProcessRecord (Resultado de resultados) Método protegido Abstract ProcessRecord (ResultSet Result) lanza SQLException; public void ejecute (string sql, object [] parámetros) lanza SQLException {Connection Connection = null; Declaración preparada = nulo; ResultSet result = null; intente {Connection = OpenConnection (); instrucción = conexión.PrepareStatement (SQL); for (int i = 0; i <parameters.length; i ++) {Declary.SetObject (i, parámetros [i]); } resultado = Declary.ExCuteQuery (); while (result.next ()) {ProcessRecord (resultado); }} finalmente {if (resultado! = null) {try {result.close (); } catch (sqlexception e) { / * ignorar * /}} if (declaración! = null) {try {stattle.close (); } catch (sqlexception e) { / * ignorar * /}} if (declaración! = null) {try {stattle.close (); } catch (sqlexception e) { / * ignorar * /}} if (conexión! = null) {Closeconnection (conexión); }}}}Esta es una subclase que extiende JDBCContext para leer la lista de usuarios:
Public Class Readusers extiende JDBCContext {List Users = new ArrayList (); Public Readusers (DataSource DataSource) {super (DataSource); } Lista pública getUsers () {return this.users; } ProcessRecord void protegido (resultado de resultados) {user user = new user (); user.setName (result.getString ("nombre")); user.SetEmail (result.getString ("correo electrónico")); ussers.add (usuario); }}Aquí es cómo usar la clase Readusers:
ReadUsers readusers = new Readusers (DataSource); readusers.execute ("Seleccionar * de usuarios", nuevo objeto [0]); List Users = readusers.getUsers (); Si la clase Readusers necesita obtener una conexión desde el grupo de conexión y liberarla nuevamente al grupo de conexión después de usar, puede insertar la conexión anulando openConnection() y closeConnection(Connection connection) .
Tenga en cuenta cómo reescribir el código de operación de insertar a través del método. La subclase de JDBCContext anula el método ProcessRecord para proporcionar un procesamiento de registros especial. En el ejemplo de StreamContext, el código de operación se encapsula en un objeto separado y se proporciona como un parámetro de método. El objeto que implementa la interfaz de operación StreamProcessor se pasa como un parámetro al método ProcessStreamContext ClassStream processStream(...) .
Puede usar ambas técnicas al implementar el contexto. La clase JDBCCContext puede pasar los objetos ConnectePener y ConnectionCloser que implementan la interfaz de operación como parámetros al método Ejecutar, o como parámetros del constructor. Personalmente, prefiero usar objetos de operación separados e interfaces de operación por dos razones. Primero, hace que sea más fácil probar el código de operación solo; En segundo lugar, hace que el código de operación sea reutilizable en múltiples contextos. Por supuesto, el código de operación también se puede usar en múltiples lugares del código, pero esto es solo una ventaja. Después de todo, aquí solo estamos tratando de reutilizar el contexto, no reutilizar las operaciones.
Conclusión
Ahora ha visto dos formas diferentes de reutilizar el código. Reutilización de características clásicas y reutilización de contexto menos común. Esperemos que la reutilización del contexto sea tan común como la reutilización de características. La reutilización de contexto es una forma muy útil de abstragar el código de los detalles subyacentes de una API (como JDBC, IO o API NIO, etc.). Especialmente si la API contiene recursos que deben administrarse (encender y cerrar, obtener y regresar, etc.).
Persistencia/API ORM, Mr.Persister utiliza la reutilización de contexto para lograr la conexión automática y la gestión del ciclo de vida de las transacciones. De esta manera, el usuario nunca tendrá que preocuparse por abrir o cerrar la conexión correctamente, o cometer o rodar hacia atrás la transacción. Mr.Persister proporciona contexto en el que los usuarios pueden insertar sus operaciones. Estos contextos son responsables de abrir, cerrar, cometer y rodar hacia atrás.
El popular marco de primavera contiene una gran reutilización del contexto. Por ejemplo, Springs JDBC Abstracción. Los desarrolladores de primavera lo usan como una "inversión de control". Este no es el único tipo de inversión de control utilizado por Spring Frameworks. La característica central de Spring son las fábricas de frijoles de inyección de dependencia o "contextos de aplicación". La inyección de dependencia es otro tipo de inversión de control.
Lo anterior es la función y la reutilización del contexto del código Java que el editor le presentó. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!