Мне вряд ли нужно обсудить, почему повторное использование кода полезно. Повторное использование кода обычно делает разработку программы быстрее и уменьшает ошибки. После того, как кусок кода инкапсулируется и используется повторно, необходимо проверить очень маленький кусок кода, чтобы обеспечить правильность программы. Если вам нужно только открыть и закрыть подключение к базе данных в одном месте на протяжении всего приложения, гораздо проще убедиться, что соединение является нормальным. Но я уверен, что вы уже знаете все это.
Есть два типа кодов повторного использования, которые я называю типами повторного использования:
Первым типом является функциональное повторное использование, которое является наиболее распространенным типом повторного использования. Это также своего рода мастерство для большинства разработчиков. То есть повторно используйте набор последующих инструкций для выполнения некоторой операции.
Второй тип - это повторное использование контекста, то есть различные функции или коды операций инкапсулируются между теми же контекстами, и тот же контекст инкапсулируется, как код повторного использования (контекст здесь относится к ряду тех же инструкций по операции). Хотя он становится все более популярным в обращении с контролем, это не распространено. Более того, повторное использование контекста не описывается явно, поэтому он не используется системой, такой как функциональное повторное использование. Я надеюсь, что вы изменитесь после прочтения этой статьи.
Повторное использование функции
Функциональное повторное использование является наиболее распространенным типом повторного использования. Это повторное использование набора инструкций, которые выполняют какую -то операцию. Следующие два метода должны считать данные из базы данных:
public List Readallusers () {connection Connection = null; String sql = "select * от пользователей"; Список пользователей = new ArrayList (); try {connection = openConnection (); Ratemstatement ratement = connection.prepareStatement (SQL); Результаты результата = оператор.executeQuery (); while (result.next ()) {// повторно использовать код пользователь пользователь = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("email")); users.add (пользователь); // код повторного использования End} result.close (); Заявление.close (); вернуть пользователей; } catch (sqlexception e) {// Игнорировать сейчас} наконец {// Игнорировать сейчас}} public list readusersofstatus (string status) {connection connection = null; String sql = "select * из пользователей, где status =?"; Список пользователей = new ArrayList (); try {connection = openConnection (); Ratemstatement ratement = connection.prepareStatement (SQL); atpution.setString (1, Status); Результаты результата = оператор.executeQuery (); while (result.next ()) {// повторно использовать код пользователь пользователь = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("email")); users.add (пользователь); // код повторного использования End} result.close (); Заявление.close (); вернуть пользователей; } catch (sqlexception e) {// Игнорировать сейчас} наконец {// Игнорировать сейчас}}Для опытных разработчиков можно скоро обнаружить многоразовый код. Место, где «код повторного использования» комментируется в приведенном выше коде, такое же, поэтому повторное использование может быть инкапсулировано. Это операции, которые читают записи пользователей в экземпляры пользователей. Эти строки кода могут быть инкапсулированы в свои собственные методы, например:
// инкапсулировать ту же операцию в метод чтения частного пользователя Readuser (результат результатов), который выбрасывает sqlexception {user user = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("email")); users.add (пользователь); вернуть пользователь; }Теперь вызовите метод ReadUser () в двух вышеуказанных методах (в следующем примере показан только первый метод):
public List Readallusers () {connection Connection = null; String sql = "select * от пользователей"; Список пользователей = new ArrayList (); try {connection = openConnection (); Ratemstatement ratement = connection.prepareStatement (SQL); Результаты результата = оператор.executeQuery (); while (result.next ()) {users.add (readuser (result))} result.close (); Заявление.close (); вернуть пользователей; } catch (sqlexception e) {// Игнорировать сейчас} наконец {// Игнорировать сейчас}}Метод ReadUser () также может быть скрыт в своем собственном классе, используя модификатор Private.
Выше приведено о повторном использовании функций. Функциональное повторное использование заключается в том, чтобы инкапсулировать набор инструкций, которые выполняют конкретные операции с помощью методов или классов для достижения цели повторного использования.
Параметризованные операции
Иногда вы хотите повторно использовать набор операций, но эти операции не совсем то же самое, где вы используете. Например, методы readallusers () и readusersofstatus () как открывают соединение, подготавливают оператор, выполняют его и проходят через набор результатов. Единственное отличие состоит в том, что readusersofstatus () требует установки параметра на подготовленном предприятии. Мы можем инкапсулировать все операции в метод ReadUserList (). Как показано ниже:
Частный список ReadUserList (String SQL, String [] Параметры) {Connection Connection = null; Список пользователей = new ArrayList (); try {connection = openConnection (); Ratemstatement ratement = connection.prepareStatement (SQL); for (int i = 0; i <parameters.length; i ++) {ratement.setString (i, параметры [i]); } ResultSet result = ratement.executeQuery (); while (result.next ()) {users.add (readuser (result))} result.close (); Заявление.close (); вернуть пользователей; } catch (sqlexception e) {// Игнорировать сейчас} наконец {// Игнорировать сейчас}} Теперь мы называем метод readUserList(...) от readAllUsers() и readUsersOfStatus() и даем различные параметры работы:
Общедоступный список readallusers () {return readuserlist ("select * from users", new String [] {});} public list readuserswithstatus (string status) {return reateUserlist ("select * from users", new String [] {status});}Я считаю, что вы можете найти другие лучшие способы реализации функций повторного использования и параметризации их, чтобы упростить использование.
Повторное использование контекста
Повторное использование контекста немного отличается от повторного использования функций. Повторное использование контекста - это повторное использование ряда инструкций, и между этими инструкциями всегда выполняются различные операции. Другими словами, повторно используйте заявления до и после различных поведений. Поэтому повторное использование контекста часто приводит к инверсии классов стиля управления. Повторное использование контекста является очень эффективным способом повторного использования обработки исключений, управления жизненным циклом соединений и транзакций, иразации потока и выключения, а также многих других общих операционных контекстов.
Вот два метода, которые выполняются с помощью inputstream:
public void printStream (inputstream inputstream) бросает ioException {if (inputstream == null) return; IOException Exception = null; try {int income = inputstream.read (); while (символ! = -1) {System.out.print ((char) символ); // разные символы = inputstream.read (); }} наконец {try {inputStream.close (); } catch (ioException e) {if (exception == null) брось E; }}} public String readstream (InputStream InputStream) Throws ioException {StringBuffer buffer = new StringBuffer (); // разные if (inputstream == null) return; IOException Exception = null; try {int income = inputstream.read (); while (символ! = -1) {buffer.append ((char) символ); // разные символы = inputstream.read (); } return buffer.toString (); // разные} наконец {try {inputStream.close (); } catch (ioException e) {if (exception == null) брось E; }}}Два метода отличаются от операции потока. Но контекст вокруг этих операций такой же. Код контекста итерации и закрывает InputStream. В дополнение к различиям в использовании отметок комментариев, приведенный выше код является кодом контекста.
Как показано выше, контекст включает в себя обработку исключений и гарантирует, что поток закрыт правильно после итерации. Написание такой обработки ошибок и кода выпуска ресурсов снова и снова является громоздким и подверженным ошибкам. Обработка ошибок и правильная обработка соединения более сложны в транзакциях JDBC. Очевидно, проще написать код один раз и повторно использовать его где угодно.
К счастью, метод инкапсулирования контекста прост. Создайте контекстный класс и поместите в него публичный контекст. При использовании контекста различные инструкции по эксплуатации абстрагируются в интерфейс операции, а затем каждая операция инкапсулируется в классе, который реализует интерфейс операции (называемый класс операции здесь). Вам нужно только вставить экземпляр класса операции в контекст. Это может быть сделано путем передачи экземпляра класса операции в качестве параметра конструктору объекта контекста или передачи экземпляра класса операции в качестве параметра конкретному методу выполнения контекста.
Следующее показывает, как разделить приведенный выше пример на контекст и эксплуатационный интерфейс. StreamProcessor (операционный интерфейс) передается в качестве параметра методу ProcedStream () StreamProcessorContext.
// Потоковая обработка плагина интерфейс публичный интерфейс StreamProcessor {public void (int input);} // Процесс обработки потока класс Общедоступный класс Public ProcessorcessorcessOntext {// создание интерфейса операции StreamProcessor и служить как параметр public void ProcessStream (inputStream, процесс StreamProcessor) throws IoException {if (INPUTSTREAM = null); IOException Exception = null; try {int income = inputstream.read (); while (символ! = -1) {processor.process (символ); символ = inputstream.read (); }} наконец {try {inputStream.close (); } catch (ioException e) {if (exception == null) брось E; бросить исключение; }}}}Теперь вы можете использовать класс StreamProcessorContext, чтобы распечатать содержимое потока, как следующий пример:
FileInputStream inputStream = new FileInputStream ("myFile"); // Пример операции через анонимную подкласс реализацию интерфейса StreamProcessor new StreamProcessorContext (). ProcedStream (inputStream, new Streamprocessor () {public void Process (int input) {system.out.print ((char) вход);Или прочитайте содержание потока ввода, подобное этому и добавьте его в последовательность символов:
Public Class StreamToStringReader реализует StreamProcessor {private StringBuffer Buffer = new StringBuffer (); public StringBuffer getBuffer () {return this.buffer; } public void Process (int input) {this.buffer.append ((char) input); }} FileInputStream inputStream = new FileInputStream ("myFile"); StreamToStringReader Reader = new StreamToStringReader (); new StreamProcessorContext (). ProcedStream (InputStream, Reader); // сделайте что -то с вводом от stream.read.getbuffer ();Как видите, сделайте что угодно с потоком, вставив другую реализацию интерфейса интерфейса Streamprocessor. Как только StreamProcessorContext полностью реализован, у вас никогда не будет никаких проблем с неподходящими потоками.
Повторное использование контекста очень мощное и может использоваться во многих других средах за пределами обработки потоков. Очевидным вариантом использования является правильное обработку подключений и транзакций в базе данных ( open - process - commit()/rollback() - close() ). Другими вариантами использования являются обработка каналов NIO и синхронизация потоков в критических разделах ( lock() - access shared resource - unlock() ). Это также может преобразовать проверенные исключения из API в неконтролируемые исключения.
Когда вы ищете код, подходящий для повторного использования контекста в вашем проекте, ищите следующие режимы операции:
Когда вы находите такую шаблон, регулярные операции до и после могут достичь повторного использования контекста.
Контекст как метод шаблона
Иногда вы захотите иметь несколько точек плагина в контексте. Если контекст состоит из многих меньших шагов, и вы хотите, чтобы каждый шаг контекста был настраиваемым, вы можете реализовать контекст в качестве метода шаблона. Метод шаблона - это шаблон проектирования GOF. По сути, метод шаблона делит алгоритм или протокол на серию этапов. Метод шаблона обычно реализуется в виде единого базового класса и предоставляет метод для каждого шага в алгоритме или протоколе. Чтобы настроить любой шаг, просто создайте класс, который расширяет базовый класс метода шаблона, и переопределяйте метод шага, который вы хотите настроить.
Следующий пример - JDBCContext, реализованный как метод шаблона. Подклассы могут переопределить открытие и закрытие соединений, чтобы обеспечить пользовательское поведение. Метод ProcessRecord (результат результатов) всегда должен быть переопределен, потому что он абстрактный. Этот метод предоставляет операции, которые не находятся в контексте и отличаются в разных случаях с использованием JDBCContext. Этот пример не является идеальным JDBCContext. Он используется только для демонстрации того, как использовать методы шаблона при реализации контекста.
открытый абстрактный класс jdbccontext {dataSource dataSource = null; // Конструктор без параметров может использоваться для подклассов без данных DataSource, чтобы получить соединение public jdbcContext () {} public jdbcContext (dataSource DataSource) {this.DataSource = dataSource; } Защищенное соединение OpenConnection () Throws SQLexception {return dataSource.getConnection (); } Защищенный void closeConnection (соединение соединения) Throws SQLexception {connection.Close (); } // ProcessRecord (ResultSet Result) Метод защищенный абстрактный ProcessRecord (Результат ResultSet) THRES SQLEXCECTION; public void execute (string sql, object [] параметры) выбрасывает sqlexception {connection connection = null; Заявление PrectStatement = null; Результат результата = null; try {connection = openConnection (); оператор = connection.prepareStatement (SQL); for (int i = 0; i <parameters.length; i ++) {ratement.setObject (i, параметры [i]); } result = ratement.executeQuery (); while (result.next ()) {processrecord (result); }} наконец {if (result! = null) {try {result.close (); } catch (sqlexception e) { / * игнорировать * /}} if (ratement! = null) {try {ratement.close (); } catch (sqlexception e) { / * игнорировать * /}} if (ratement! = null) {try {ratement.close (); } catch (sqlexception e) { / * Игнорировать * /}} if (connection! = null) {closeConnection (connection); }}}}Это подкласс, который расширяет JDBCContext для чтения списка пользователей:
Public Class Readusers Extends JDBCContext {List users = new ArrayList (); public ReadsUsers (DataSource DataSource) {Super (DataSource); } public list getUsers () {return this.users; } Protected void ProcessRecord (ResultSet Result) {user user = new user (); user.setName (result.getString ("name")); user.setemail (result.getString ("email")); users.add (пользователь); }}Вот как использовать класс ReadUsers:
ReadUsers ReadUsers = new ReadUsers (dataSource); readusers.execute ("select * из пользователей", новый объект [0]); список пользователей = readusers.getUsers (); Если класс ReaduSers должен получить соединение из пула соединений и выпустить его обратно в пул соединений после использования, вы можете вставить соединение, переопределив методы openConnection() и closeConnection(Connection connection) .
Обратите внимание, как переписать код операции вставки через метод. Подкласс JDBCContext переопределяет метод ProcessRecord для обеспечения специальной обработки записей. В примере StreamContext код работы инкапсулируется в отдельном объекте и предоставляется в качестве параметра метода. Объект, который реализует трансфейс интерфейс -интерфейс, передается в качестве параметра методу ProcedStreamContext Class processStream(...) .
Вы можете использовать оба метода при реализации контекста. Класс JDBCContext может передавать объекты ConnectionOpener и ConnectionCloser, которые реализуют интерфейс операции как параметры для метода выполнения, или как параметры конструктора. Лично я предпочитаю использовать отдельные операционные объекты и операционные интерфейсы по двум причинам. Во -первых, это облегчает проверку единичного кода операции в одиночку; Во -вторых, он делает код операции повторно используемым в нескольких контекстах. Конечно, код операции также можно использовать в нескольких местах в коде, но это просто преимущество. В конце концов, здесь мы просто пытаемся повторно использовать контекст, а не повторно использовать операции.
Заключение
Теперь вы видели два разных способа повторного использования кода. Классическое повторное использование функций и менее распространенное повторное использование контекста. Надеемся, что повторное использование контекста будет столь же распространено, как повторное использование функций. Повторное использование контекста является очень полезным способом абстрактного кода из основных деталей API (например, JDBC, IO или NIO API и т. Д.). Особенно, если API содержит ресурсы, которыми необходимо управлять (включить и закрывать, получить и возвращать и т. Д.).
Постоянство/ORM API, Mr.Persister использует повторное использование контекста для достижения автоматического управления жизненным циклом соединения и транзакций. Таким образом, пользователю никогда не придется беспокоиться о правильном открытии или закрытии подключения, о том, чтобы совершить или откатить транзакцию. Г -н Spersister предоставляет контекст, в котором пользователи могут вставлять свои операции. Эти контексты несут ответственность за открытие, закрытие, совершение и откат.
Популярная весенняя структура содержит много повторного использования контекста. Например, Springs JDBC Abstraction. Разработчики Spring используют его как «изменение управления». Это не единственный тип инверсии управления, используемый пружинными рамками. Основной особенностью пружины являются фабрики впрыскивания зависимости или «контексты применения». Инъекция зависимости является еще одним типом контрольной инверсии.
Выше приведено функция и повторное использование контекста кода Java, которое редактор представил вам. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!