Ich muss kaum diskutieren, warum das Wiederverwenden von Code von Vorteil ist. Die Wiederverwendung von Code macht die Programmentwicklung in der Regel schneller und reduziert Fehler. Sobald ein Stück Code eingekapselt und wiederverwendet wird, muss ein sehr kleiner Code überprüfen, um die Richtigkeit des Programms zu gewährleisten. Wenn Sie die Datenbankverbindung nur an einem Ort während der gesamten Anwendung öffnen und schließen müssen, ist es viel einfacher sicherzustellen, dass die Verbindung normal ist. Aber ich bin sicher, Sie wissen das alles schon.
Es gibt zwei Arten von Wiederverwendungscodes, die ich Wiederverwendungstypen nenne:
Der erste Typ ist die funktionale Wiederverwendung, die die häufigste Art der Wiederverwendung ist. Dies ist auch für die meisten Entwickler eine Art Meisterschaft. Das heißt, eine Reihe nachfolgender Anweisungen zur Durchführung eines Betriebs zu verwenden.
Der zweite Typ ist die Wiederverwendung von Kontext, dh unterschiedliche Funktionen oder Betriebscodes werden zwischen denselben Kontexten eingekapselt, und der gleiche Kontext wird als Wiederverwendungscode eingekapselt (der Kontext bezieht sich hier auf eine Reihe derselben Operationsanweisungen). Obwohl es in der Kontrollumkehr immer beliebter wird, ist es nicht üblich. Darüber hinaus wird die Wiederverwendung von Kontext nicht explizit beschrieben, so dass das System nicht wie die funktionale Wiederverwendung verwendet wird. Ich hoffe, Sie ändern sich nach dem Lesen dieses Artikels.
Funktion Wiederverwendung
Die funktionale Wiederverwendung ist die häufigste Art der Wiederverwendung. Es ist eine Wiederverwendung einer Reihe von Anweisungen, die eine Art von Operation ausführen. Die folgenden zwei Methoden sind das Lesen von Daten aus der Datenbank:
public list readAllusers () {Connection Connection = null; String SQL = "Select * von Benutzern"; Listen user = new ArrayList (); try {Connection = openConnection (); PreparedStatement Anweisung = Connection.Preparestatement (SQL); ResultSet result = Anweisung.executeQuery (); while (result.Next ()) {// Code -CODE user user = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("E -Mail")); users.Add (Benutzer); // REUSE -CODE} result.close (); Erklärung.CLOSE (); Rückkehrbenutzer; } catch (SQLEXception e) {// Ignorieren Sie vorerst} endlich {// Ignorieren Sie für den Moment}} public List ReadUsersOfStatus (String -Status) {Connection Connection = null; String sql = "Select * von Benutzern, wo status =?"; Listen user = new ArrayList (); try {Connection = openConnection (); PreparedStatement Anweisung = Connection.Preparestatement (SQL); Erklärung.SetString (1, Status); ResultSet result = Anweisung.executeQuery (); while (result.Next ()) {// Code -CODE user user = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("E -Mail")); users.Add (Benutzer); // REUSE -CODE} result.close (); Erklärung.CLOSE (); Rückkehrbenutzer; } catch (SQLEXception e) {// Ignorieren Sie vorerst} endlich {// Ignorieren Sie für den Moment}}Für erfahrene Entwickler kann es möglich sein, bald wiederverwendbare Code zu entdecken. Der Ort, an dem "Wiederverwendung Code" im obigen Code kommentiert wird, ist der gleiche, daher kann die Wiederverwendung eingekapselt werden. Dies sind die Vorgänge, die Benutzerdatensätze in Benutzerinstanzen lesen. Diese Codezeilen können beispielsweise in ihre eigenen Methoden in ihre eigenen Methoden eingefasst werden:
// In der gleichen Operation in die ReadUser -Methode einbeziehen private Benutzer ReadUser (Ergebnisset -Ergebnis) löst SQLEXception {user user = new user () aus; user.setName (result.getString ("name")); user.setemail (result.getString ("E -Mail")); users.Add (Benutzer); Benutzer zurückgeben; }Rufen Sie nun die Methode ReadUser () in den beiden oben genannten Methoden auf (das folgende Beispiel zeigt nur die erste Methode):
public list readAllusers () {Connection Connection = null; String SQL = "Select * von Benutzern"; Listen user = new ArrayList (); try {Connection = openConnection (); PreparedStatement Anweisung = Connection.Preparestatement (SQL); ResultSet result = Anweisung.executeQuery (); while (result.next ()) {user.add (readUser (result))} result.close (); Erklärung.CLOSE (); Rückkehrbenutzer; } catch (SQLEXception e) {// Ignorieren Sie vorerst} endlich {// Ignorieren Sie für den Moment}}Die ReadUser () -Methode kann auch in seiner eigenen Klasse unter Verwendung des Modifikator Private versteckt werden.
In der oben genannten Funktionen geht es um die Wiederverwendung von Funktionen. Die funktionale Wiederverwendung besteht darin, eine Reihe von Anweisungen zu verkörpern, die bestimmte Operationen durch Methoden oder Klassen ausführen, um den Zweck der Wiederverwendung zu erreichen.
Parametrisierte Operationen
Manchmal möchten Sie eine Reihe von Operationen wiederverwenden, aber diese Operationen sind überall nicht gleich, wo Sie verwenden. Beispielsweise öffnen ReadallUsers () und ReadUsersOfStatus () -Methoden eine Verbindung, bereiten eine Anweisung vor, führen Sie sie aus und schleifen Sie die Ergebnismenge durch. Der einzige Unterschied besteht darin, dass ReadUsersOfStatus () einen Parameter auf vorbereitete Stellungen eingestellt werden muss. Wir können alle Operationen in eine ReadUserList () -Methode integrieren. Wie unten gezeigt:
private list readUerList (String SQL, String [] Parameter) {Connection Connection = null; Listen user = new ArrayList (); try {Connection = openConnection (); PreparedStatement Anweisung = Connection.Preparestatement (SQL); für (int i = 0; i <parameter.length; i ++) {Anweisung.SetString (i, Parameter [i]); } ResultSet result = Anweisung.executeQuery (); while (result.next ()) {user.add (readUser (result))} result.close (); Erklärung.CLOSE (); Rückkehrbenutzer; } catch (SQLEXception e) {// Ignorieren Sie vorerst} endlich {// Ignorieren Sie für den Moment}} Jetzt nennen wir readUserList(...) -Methode von readAllUsers() und readUsersOfStatus() und geben unterschiedliche Betriebsparameter an:
public list readAllusers () {return readUserList ("aus den Benutzern auswählen", neuer String [] {});} public list readUsersWithStatus (String -Status) {return ReadUserList ("aus den Benutzern auswählen", neuer String [] {Status});};};};};};Ich glaube, Sie können andere bessere Möglichkeiten finden, um Wiederverwendungsfunktionen zu implementieren und sie zu parametriieren, um die Verwendung zu erleichtern.
Kontext -Wiederverwendung
Die Rückverwendung von Kontext unterscheidet sich geringfügig von der Wiederverwendung von Merkmalen. Die Wiederverwendung von Kontext ist die Wiederverwendung einer Reihe von Anweisungen, und zwischen diesen Anweisungen werden immer verschiedene Operationen durchgeführt. Mit anderen Worten, Wiederverwenden von Aussagen vor und nach verschiedenen Verhaltensweisen. Daher führt die Wiederverwendung von Kontext häufig zu einer Umkehrung der Kontrollstilklassen. Die Wiederverwendung von Kontext ist eine sehr effektive Möglichkeit, Ausnahmeregelung, Verbindungs- und Transaktionslebenszyklusmanagement, Durchfluss -Iteration und -abstillung sowie viele andere gemeinsame operative Kontexte wiederzuverwenden.
Hier sind zwei Methoden, die mit InputStream durchgeführt werden:
public void printstream (InputStream InputStream) löst IOException {if (inputStream == null) zurück; IOException AUCECT = NULL; try {int charakter = inputStream.read (); while (Zeichen! = -1) {System.out.print ((char) Zeichen); // verschiedene Zeichen = inputStream.read (); }} schließlich {try {inputStream.close (); } catch (ioException e) {if (exception == null) werfen e; }}} public String readStream (inputStream InputStream) löst IOException {stringBuffer buffer = new StringBuffer () aus; // unterschiedlich if (InputStream == NULL) Return; IOException AUCECT = NULL; try {int charakter = inputStream.read (); while (Zeichen! = -1) {buffer.Append ((char) Zeichen); // verschiedene Zeichen = inputStream.read (); } return buffer.toString (); // unterschiedlich} endlich {try {inputStream.close (); } catch (ioException e) {if (exception == null) werfen e; }}}Die beiden Methoden unterscheiden sich vom Flussbetrieb. Aber der Kontext um diese Operationen ist der gleiche. Der Kontextcode iteriert und schließt den InputStream. Zusätzlich zu den Unterschieden bei der Verwendung von Kommentarmarken ist der obige Code sein Kontextcode.
Wie oben gezeigt, beinhaltet der Kontext die Ausnahmebehandlung und stellt sicher, dass der Strom nach der Iteration korrekt geschlossen wird. Das Schreiben eines solchen Fehlers zur Handhabung und des Ressourcenfreigabe ist immer wieder umständlich und fehleranfällig. Fehlerbehebung und korrekte Verbindungshandhabung sind in JDBC -Transaktionen komplexer. Es ist offensichtlich einfacher, einen Code einmal zu schreiben und ihn überall wieder zu verwenden.
Glücklicherweise ist die Methode zur Einkapselung des Kontextes einfach. Erstellen Sie eine Kontextklasse und geben Sie den öffentlichen Kontext ein. In der Verwendung des Kontextes werden verschiedene Betriebsanweisungen in die Operationsschnittstelle abstrahiert, und dann wird jeder Vorgang in der Klasse eingekapselt, die die Operationsschnittstelle implementiert (hier als Betriebsklasse bezeichnet). Sie müssen nur eine Instanz der Operationsklasse in den Kontext einfügen. Dies kann durch Übergeben einer Instanz der Operationsklasse als Parameter an den Konstruktor des Kontextobjekts oder durch Übergeben einer Instanz der Operationsklasse als Parameter an die spezifische Ausführungsmethode des Kontextes durchgeführt werden.
Im Folgenden wird angezeigt, wie das obige Beispiel in den Kontext und die operative Schnittstelle unterteilt wird. StreamProcessor (Operation Interface) wird als Parameter an die processStream () -Methode des StreamProcessorContext übergeben.
// Stream Processing -Plugin -Schnittstelle öffentliche Schnittstelle StreamProcessor {public void prozess (int input);} // Stream Processing Context Class öffentlich Klasse StreamProcessorContext {// die StreamProcessor -Operation -Schnittstelle instanziieren und als Parameter public void processStream (InputStream, StreamProcessor) dienen. IOException AUCECT = NULL; try {int charakter = inputStream.read (); while (Zeichen! = -1) {processor.process (Zeichen); Zeichen = inputStream.read (); }} schließlich {try {inputStream.close (); } catch (ioException e) {if (exception == null) werfen e; Ausnahme werfen; }}}}Jetzt können Sie die StreamProcessorContext -Klasse verwenden, um die Stream -Inhalte wie das folgende Beispiel auszudrucken:
FileInputStream InputStream = new FileInputStream ("myFile"); // Beispiel für die Operation durch anonyme Subklasse -Implementierung der StreamProcessor -Schnittstelle Neue StreamProcessorContext (). ProcessStream (InputStream, New StreamProcessor () {Public void prozes (int Input) {Outs.Out.Print (char) (char) (Char) input);Oder lesen Sie den Inhalt des Eingabestreams wie diesen und fügen Sie ihn einer Zeichensequenz hinzu:
öffentliche Klasse StreamToStringReader implementiert StreamProcessor {private StringBuffer buffer = new StringBuffer (); public StringBuffer getBuffer () {return this.Buffer; } public void prozess (int input) {this.buffer.Append ((char) input); }} FileInputStream inputStream = new FileInputStream ("myFile"); StreamToStringReader reader = new StreamToStringReader (); new StreamProcessorContext () processStream (inputStream, Reader); // Machen Sie etwas mit Eingabe von Stream.Reader.getBuffer ();;Wie Sie sehen können, tun Sie alles mit dem Stream, indem Sie eine andere Implementierung der StreamProcessor -Schnittstelle einfügen. Sobald der StreamProcessorContext vollständig implementiert ist, werden Sie niemals Probleme mit nicht abgestellten Streams haben.
Die Wiederverwendung von Kontext ist sehr leistungsstark und kann in vielen anderen Umgebungen außerhalb der Stream -Verarbeitung verwendet werden. Ein offensichtlicher Anwendungsfall besteht darin, Datenbankverbindungen und -transaktionen korrekt zu verarbeiten ( open - process - commit()/rollback() - close() ). Andere Anwendungsfälle sind die NIO -Kanalverarbeitung und Threadsynchronisation in kritischen Abschnitten ( lock() - access shared resource - unlock() ). Es kann auch überprüfte Ausnahmen von der API in deaktivierte Ausnahmen konvertieren.
Wenn Sie nach Code suchen, der für die Wiederverwendung von Kontext in Ihrem Projekt geeignet ist, suchen Sie nach den folgenden Betriebsmodi:
Wenn Sie ein solches Muster finden, können die regulären Operationen vor und nach der Wiederverwendung von Kontext erreichen.
Kontext als Vorlagenmethode
Manchmal möchten Sie mehrere Pluginpunkte im Kontext haben. Wenn der Kontext aus vielen kleineren Schritten besteht und dass jeder Schritt des Kontextes anpassbar ist, können Sie den Kontext als Vorlagenmethode implementieren. Die Vorlagenmethode ist ein GOF -Designmuster. Grundsätzlich unterteilt die Vorlagenmethode einen Algorithmus oder Protokoll in eine Reihe von Schritten. Eine Vorlagenmethode wird normalerweise als einzelne Basisklasse implementiert und bietet eine Methode für jeden Schritt in einem Algorithmus oder Protokoll. Um einen Schritt anzupassen, erstellen Sie einfach eine Klasse, die die Basisklasse der Vorlagenmethode erweitert, und überschreiben Sie die Methode des Schritts, den Sie anpassen möchten.
Das folgende Beispiel ist ein JDBCContext, der als Vorlagenmethode implementiert ist. Unterklassen können das Öffnen und Schließen von Verbindungen überschreiben, um ein individuelles Verhalten bereitzustellen. Die ProcessRecord -Methode (Ergebnisset -Ergebnis) muss immer überschrieben werden, da es abstrakt ist. Diese Methode liefert Operationen, die nicht im Kontext sind und in verschiedenen Fällen unter Verwendung von JDBCContext unterschiedlich sind. Dieses Beispiel ist kein perfekter JDBCContext. Es wird nur verwendet, um zu demonstrieren, wie bei der Implementierung des Kontextes Vorlagenmethoden verwendet werden.
public abstract class jdbccontext {dataSource dataSource = null; // Der Konstruktor ohne Parameter kann für Unterklassen ohne DataSource verwendet werden, um die Verbindung public jdbccontext () {} public jdbccontext (DataSource -Datenource) {thataSource = DataSource; } Protected Connection openConnection () löscht sqlexception {return DataSource.getConnection (); } Protected void CloseConnection (Verbindungsverbindung) löscht sqlexception {connection.close (); } // ProcessRecord (Ergebnisergebnis) Methode Protected Abstract ProcessRecord (ResultSet Ergebnis) löst SQLEXception aus; public void execute (String SQL, Object [] Parameter) löst SQLEXception {Connection Connection = null aus; PreparedStatement Statement = NULL; Ergebnisset Ergebnis = NULL; try {Connection = openConnection (); Anweisung = Connection.Preparestatement (SQL); für (int i = 0; i <parameter.length; i ++) {Anweisung.SetObject (i, Parameter [i]); } result = Anweisung.executeQuery (); while (result.next ()) {processrecord (result); }} endlich {if (result! = null) {try {result.close (); } catch (sqlexception e) { / * ignorieren * /}} if (Anweisung! = null) {try {Anweisung.CLOSE (); } catch (sqlexception e) { / * ignorieren * /}} if (Anweisung! = null) {try {Anweisung.CLOSE (); } catch (SQLEXception e) { / * ignorieren * /}} if (connection! = null) {CloseConnection (Verbindung); }}}}Dies ist eine Unterklasse, die den JDBCContext erweitert, um die Benutzerliste zu lesen:
öffentliche Klasse ReadUser erweitert JDBCConText {list user = new ArrayList (); public readUers (DataSource DataSource) {Super (DataSource); } public list getUsers () {return this.users; } Protected void processRecord (Ergebnis -set -Ergebnis) {user user = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("E -Mail")); users.Add (Benutzer); }}Hier erfahren Sie, wie Sie die ReadUsers -Klasse verwenden:
ReadUsers ReadUers = New ReadUers (DataSource); ReadUsers.execute ("SELECT * von Benutzern", neues Objekt [0]); list user = readUsers.getUsers (); Wenn die READUSERS -Klasse eine Verbindung aus dem Verbindungspool abrufen und nach der Verwendung wieder in den Verbindungspool abgeben muss, können Sie die Verbindung einfügen, indem Sie openConnection() und closeConnection(Connection connection) überschreiben.
Beachten Sie, wie Sie den Vorgangsvorgangscode über die Methode neu schreiben. Die Unterklasse von JDBCContext überschreibt die ProcessRecord -Methode, um eine spezielle Datensatzverarbeitung bereitzustellen. Im StreamContext -Beispiel wird der Betriebscode in einem separaten Objekt eingekapselt und als Methodeparameter bereitgestellt. Das Objekt, das den Operation Interface StreamProcessor implementiert, wird als Parameter an die ProcessStreamContext -Klasse processStream(...) übergeben.
Sie können beide Techniken verwenden, wenn Sie den Kontext implementieren. Die JDBCConText -Klasse kann ConnectionOpener- und ConnectionCloser -Objekte übergeben, die die Operationsschnittstelle als Parameter an die Ausführungsmethode oder als Parameter des Konstruktors implementieren. Persönlich bevorzuge ich aus zwei Gründen separate Betriebsobjekte und Betriebsoberflächen. Erstens erleichtert es, den Betriebscode allein zu testen. Zweitens macht der Operation Code in mehreren Kontexten wiederverwendbar. Natürlich kann der Betriebscode auch an mehreren Stellen im Code verwendet werden, dies ist jedoch nur ein Vorteil. Immerhin versuchen wir hier nur, den Kontext wiederzuverwenden und die Operationen nicht wiederzuverwenden.
Abschluss
Jetzt haben Sie zwei verschiedene Möglichkeiten gesehen, um Code wiederzuverwenden. Klassische Wiederverwendung von Features und weniger gemeinsame Wiederverwendung von Kontext. Hoffentlich ist die Wiederverwendung von Kontext genauso häufig wie die Wiederverwendung von Features. Die Rückverwendung von Kontext ist ein sehr nützlicher Weg, um Code aus den zugrunde liegenden Details einer API (wie JDBC, IO oder NIO -API usw.) abzuwehren. Vor allem, wenn die API Ressourcen enthält, die verwaltet werden müssen (ein und schließen, erhalten und zurückkehren usw.).
Persistenz/ORM -API, Herr Persisterin verwendet die Wiederverwendung von Kontext, um eine automatische Verbindungs- und Transaktionslebenszyklusmanagement zu erzielen. Auf diese Weise muss sich der Benutzer niemals Sorgen machen, die Verbindung korrekt zu öffnen oder zu schließen oder die Transaktion zu verpflichten oder zurückzurufen. Mr.Persisterin bietet einen Kontext, in dem Benutzer ihre Vorgänge einfügen können. Diese Kontexte sind dafür verantwortlich, das Öffnen, Schließen, Verhalten und Rollen zu eröffnen, zu verpflichten und zu rollen.
Das beliebte Spring -Framework enthält eine große Wiederverwendung von Kontext. Zum Beispiel entspricht die JDBC -Abstraktion. Springentwickler verwenden es als "Kontrollumkehr". Dies ist nicht der einzige Kontrollinversionstyp, der von Spring -Frameworks verwendet wird. Das Kernmerkmal von Spring sind Abhängigkeitsinjektionsbohnenfabriken oder "Anwendungskontexte". Die Abhängigkeitsinjektion ist eine andere Art der Kontrollinversion.
Das obige ist die Funktion und die Wiederverwendung von Java -Code und Kontext, den der Editor Ihnen vorgestellt hat. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird Ihnen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!