Все более популярная библиотека D3 обрабатывает странности добавления / управления svg очень хорошо. Вы можете захотеть использовать его в отличие от jQuery hacks, упомянутых здесь.
HTML
Javascript
var circle = d3.select("svg").append("circle")
.attr("r", "10")
.attr("style", "fill:white;stroke:black;stroke-width:5");
В основном это - шаблон, где Вы пишете метод, чтобы сделать вещи, которые всегда требуются, например, распределение ресурсов и очистка, и делают передачу вызывающей стороны в, "что мы хотим сделать с ресурсом". Например:
public interface InputStreamAction
{
void useStream(InputStream stream) throws IOException;
}
// Somewhere else
public void executeWithFile(String filename, InputStreamAction action)
throws IOException
{
InputStream stream = new FileInputStream(filename);
try {
action.useStream(stream);
} finally {
stream.close();
}
}
// Calling it
executeWithFile("filename.txt", new InputStreamAction()
{
public void useStream(InputStream stream) throws IOException
{
// Code to use the stream goes here
}
});
// Calling it with Java 8 Lambda Expression:
executeWithFile("filename.txt", s -> System.out.println(s.read()));
// Or with Java 8 Method reference:
executeWithFile("filename.txt", ClassName::methodName);
код вызова не должен волноваться об открываться/очищать стороне - это будет заботиться о executeWithFile
.
Это было откровенно болезненно в Java, потому что закрытия были так многословны, начиная с Java, как который могут быть реализованы 8 лямбда-выражений на многих других языках (например, лямбда-выражения C# или Groovy), и этот особый случай обрабатывается начиная с Java 7 с try-with-resources
и AutoClosable
потоки.
, Хотя "выделяют и очистка" является типичным данным примером, существует много других возможных примеров - обработка транзакции, вход, выполняя некоторый код с большим количеством полномочий и т.д. Это в основном немного похоже шаблонный шаблон метода , но без наследования.
Выполняются Вокруг Метода , то, куда Вы передаете произвольный код методу, который может выполнить установку, и/или разрушение кодируют и выполняют Ваш промежуточный код.
Java не является языком, я принял бы решение выполнить в этом. Это более стильно для передачи закрытия (или лямбда-выражение) как аргумент. Хотя объекты возможно эквивалентны закрытиям .
мне кажется, что Выполнение Вокруг Метода является видом подобных Инверсия Управления (Внедрение зависимости), что можно варьироваться для данного случая, каждый раз, когда Вы называете метод.
, Но это могло также быть интерпретировано как пример Связи Управления (говорящий метод, что сделать его аргументом, буквально в этом случае).
Выполнение Вокруг идиомы используется, когда Вы имеете необходимость, чтобы сделать что-то вроде этого:
//... chunk of init/preparation code ...
task A
//... chunk of cleanup/finishing code ...
//... chunk of identical init/preparation code ...
task B
//... chunk of identical cleanup/finishing code ...
//... chunk of identical init/preparation code ...
task C
//... chunk of identical cleanup/finishing code ...
//... and so on.
, Чтобы постараться не повторять весь этот избыточный код, который всегда выполняется "вокруг" Ваших фактических задач, Вы создали бы класс, который заботится о нем автоматически:
//pseudo-code:
class DoTask()
{
do(task T)
{
// .. chunk of prep code
// execute task T
// .. chunk of cleanup code
}
};
DoTask.do(task A)
DoTask.do(task B)
DoTask.do(task C)
Эта идиома перемещает весь сложный избыточный код в одно место и оставляет Вашу основную программу намного более читаемой (и удобный в сопровождении!)
Смотрят на это сообщение для примера C#, и эта статья для примера C++.
Это напоминает мне о шаблон разработки стратегии. Заметьте, что ссылка, на которую я указал, включает код Java для шаблона.
, Очевидно, можно было работать, "Выполняются Вокруг" путем создания инициализации и кода очистки и просто передачи в стратегии, которая будет тогда всегда обертываться в код очистки и инициализацию.
Как с любой техникой, используемой для сокращения повторения кода, Вы не должны использовать его, пока у Вас нет по крайней мере 2 случаев, где Вам нужен он, возможно, даже 3 (а-ля принцип YAGNI). Следует иметь в виду, что повторение кода удаления уменьшает обслуживание (меньше копий кода означает, что потраченное копирование меньшего количества времени фиксирует через каждую копию), но также и увеличивает обслуживание (больше общего кода). Таким образом стоимость этого приема - то, что Вы добавляете больше кода.
Этот тип техники полезен для больше, чем просто инициализации и очистки. Для того, также хорошо, когда Вы хотите облегчить вызывать свои функции (например, Вы могли использовать его в мастере так, чтобы "следующие" и "предыдущие" кнопки не нуждались в гигантских операторах выбора для решения, что сделать для движения в следующую / предыдущую страницу.
Я вижу, что у Вас есть тег Java здесь, таким образом, я буду использовать Java в качестве примера даже при том, что шаблон не является определенным для платформы.
идея состоит в том, что иногда у Вас есть код, который всегда включает тот же шаблон перед выполнением кода и после выполнения кода. Хорошим примером является JDBC. Вы всегда захватываете соединение и создаете оператор (или подготовленный оператор) прежде, чем выполнить фактический запрос и обработать набор результатов, и затем Вы всегда делаете ту же шаблонную очистку в конце - закрытие оператора и соединения.
идея с выполняется - вокруг, то, что лучше, если можно факторизовать шаблонный код. Это сохраняет Вас некоторый ввод, но причина более глубока. Это - принцип don't-repeat-yourself (DRY) здесь - Вы изолируете код к одному местоположению поэтому, если существует ошибка, или необходимо изменить его, или Вы просто хотите понять его, это - все в одном месте.
вещь это немного хитро с этим видом факторинга, хотя то, что у Вас есть ссылки, которые и "прежде" и "после того, как" должны видеть части. В примере JDBC это включало бы Соединение и (Подготовленный) Оператор. Таким образом для обработки этого Вы по существу "обертываете" свой целевой код с шаблонным кодом.
можно быть знакомы с некоторыми общими падежами в Java. Каждый - фильтры сервлета. Другой - AOP вокруг совета. Одна треть является различными xxxTemplate классами в Spring. В каждом случае у Вас есть некоторый интерфейсный объект, в который Ваш "интересный" код (говорят запрос JDBC, и обработка набора результатов) введен. Интерфейсный объект делает "перед" частью, вызывает интересный код и затем делает "после" части.
См. Также Сэндвичи с кодами , который рассматривает эту конструкцию во многих языках программирования и предлагает некоторые интересные исследования. идеи Что касается конкретного вопроса о том, почему его можно использовать, то в приведенной выше статье предлагается несколько конкретных примеров:
Такие ситуации возникают всякий раз, когда программа манипулирует общими ресурсами. API для блокировок, сокетов, файлов или соединений с базой данных может потребовать программа для явного закрытия или освобождения ресурса, который был ранее приобрела. На языке без сборки мусора программист отвечает за распределение памяти перед ее использованием и освобождение ее после его использования. В общем, различные задачи программирования требуют программа для внесения изменений, действовать в контексте этих изменений и затем отмените изменение. В таких ситуациях мы называем бутерброды с кодом.
А позже:
Бутерброды с кодом появляются во многих ситуациях программирования. Несколько общих примеры относятся к приобретению и выпуску ограниченных ресурсов, такие как блокировки, файловые дескрипторы или соединения с сокетами. В большей степени В общем случае любое временное изменение состояния программы может потребовать код сэндвич. Например, программа на основе графического интерфейса может временно игнорировать пользовательские вводы, или ядро ОС может временно отключить оборудование перебивает. Невозможность восстановить более раннее состояние в этих случаях приведет к серьезные ошибки.
В статье не рассматривается, почему не не используется эта идиома, но в ней описывается, почему идиома легко ошибиться без помощи уровня языка:
Сэндвичи с дефектным кодом возникают чаще всего. часто в присутствии исключения и связанный с ними невидимый поток управления. Верно, специальные языковые функции для управления сэндвичами кода возникают главным образом в языки, поддерживающие исключения.
Однако исключения не являются единственной причиной дефектного кода бутерброды. Всякий раз, когда вносятся изменения в код body , новые пути управления могут возникнуть проблемы с обходом кода после кода . В простейшем случае сопровождающему нужно только добавить оператор
return
в тело сэндвича для ввести новый дефект, который может привести к тихим ошибкам. Когда тело код большой и до и после широко разделены, такие ошибки может быть трудно обнаружить визуально.
Если вы хотите отличные идиомы, вот они:
//-- the target class
class Resource {
def open () { // sensitive operation }
def close () { // sensitive operation }
//-- target method
def doWork() { println "working";} }
//-- the execute around code
def static use (closure) {
def res = new Resource();
try {
res.open();
closure(res)
} finally {
res.close();
}
}
//-- using the code
Resource.use { res -> res.doWork(); }