На сегодняшний день я использую следующую реализацию образца построителя (в отличие от реализации, описанной здесь ):
public class Widget {
public static class Builder {
public Builder(String name, double price) { ... }
public Widget build() { ... }
public Builder manufacturer(String value) { ... }
public Builder serialNumber(String value) { ... }
public Builder model(String value) { ... }
}
private Widget(Builder builder) { ... }
}
Это хорошо работает для большинства ситуаций, с которыми я столкнулся, когда мне нужно построить сложный объект с различными обязательными/обязательными и необязательными параметрами. Тем не менее, в последнее время я изо всех сил пытаюсь понять, как образец приносит какую-либо пользу, когда все ваши параметры обязательны (или, по крайней мере, подавляющее большинство из них).
Одним из способов обойти это было логическое группирование параметров, передаваемых в их собственные классы, чтобы уменьшить количество параметров, передаваемых конструктору построителя.
Например, вместо:
Widget example = new Widget.Builder(req1, req2, req3,req4,req5,req6,req7,req8)
.addOptional(opt9)
.build();
группируется следующим образом:
Object1 group1 = new Object1(req1, req2, req3, req4);
Object2 group2 = new Object2(req5, req6);
Widget example2 = new Widget.Builder(group1, group2, req7, req8)
.addOptional(opt9)
.build();
Хотя наличие отдельных объектов немного упрощает вещи, это также немного затрудняет следование, если кто-то не знаком с кодом. Одна вещь, которую я считал, это перемещение всех параметров в свои собственные методы addParam (param)
, а затем проверка необходимых параметров в методе build ()
.
Что такое передовая практика и есть ли, возможно, лучший подход к этому, который я не рассматривал?
-121--642593-
Я использую вершинный буферный объект (VBO) в OpenGL ES 2,0.
У меня есть набор вершинных данных, которые постоянно хранятся в обычной оперативной памяти. Причина в том, что вычисление положений вершин с нуля является дорогостоящим, но дельта может быть добавлена к последней позиции, чтобы дешево обновить ее.
Фактическое количество вычерчиваемых вершин быстро изменяется с течением времени. В одном кадре я могу иметь 1000 и в следующем 2500. Следуя совету, полученному здесь ранее, я теперь указываю целое число UPPER
как верхнюю границу числа вершин, которые когда-либо будут нарисованы. Я malloc
мои массивы данных вершин и индексов только один раз при запуске на основе этого значения.
Я передаю подсказку использования GL _ STREAM _ DRAW
каждому вызову glBindBuffer
, чтобы указать, что данные изменяют каждый кадр.
Пытаясь быть максимально эффективным, я создал следующую установку:
// SETUP: Called only once.
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for UPPER vertices.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (UPPER-1).
glEnableVertexAttribArray(...); // Setup vertex attributes.
glVertexAttribPointer(...);
glUseProgram(...); // Use program with custom shaders.
glUniformMatrix4fv(...); // Identify shader uniforms.
// UPDATE: Called when vertex data changes (on each frame).
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferSubData(GL_ARRAY_BUFFER,...); // Update VBO data.
// RENDER: Called on each frame.
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...); // Number of vertices and indices to be used is inherently specified in here.
Однако это происходит с помощью EXC _ BAD _ ACCESS
на glDrawElements
, и я знаю, что это связано с упорядочением команд gl
.
У меня была похожая настройка, которая работала ранее:
// UPDATE: Called when vertex data changes (on each frame).
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (actual number of vertices to draw - 1)
// RENDER: Called on each frame.
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for actual number of vertices (not UPPER).
glEnableVertexAttribArray(...); // Setup vertex attributes.
glVertexAttribPointer(...);
glUseProgram(...); // Use program with custom shaders.
glUniformMatrix4fv(...); // Identify shader uniforms.
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...);
Однако эта настройка требует гораздо больше работы на кадр, и, как вы видите, включает изменение размеров VBO (поскольку он использует фактический размер, а не UPPER
), что, как мне сказали, является большой утечкой производительности.
Не могли бы кто-нибудь объяснить мне какие-либо очевидные проблемы с моей новой настройкой, и самое главное, какие команды я должен вызывать каждый кадр перед glDrawElements
? Мое предположение, что я могу подготовить все возможные индексы заранее, а затем передать фактическое число вершин в glDrawElements
, явно неверно.