Это большой вопрос. Я считаю, что вы спрашиваете, как добиться полиморфизма с помощью дизайна, ориентированного на данные (DOD)?
Краткий ответ: Вы не делаете этого с помощью интерфейсов. Это способ объектно-ориентированного программирования (ООП) для достижения полиморфизма. В DOD полимофизм может быть достигнут с помощью паттерна Entity Component System (ECS).
Длинный ответ (с примерами):
Вот пример полиморфизма в ООП:
public interface Drawable
{
void Draw();
}
public class Circle: Drawable
{
public float posX, posY;
public float radius;
public void Draw() { /* Draw Circle */ }
}
public class Rectangle: Drawable
{
public float posX, posY;
public float width, height;
public void Draw() { /* Draw Rectangle */ }
}
А вот как добиться полиморфизма с помощью DOD и ECS (псевдокода):
public struct Position { public float x, y; }
public struct Circle { public float radius; }
public struct Rectangle { public float width, height; }
public class DrawCirlceSystem
{
public void OnUpdate()
{
ComponentQuery
.SelectReadOnly(typeof(Position), typeof(Circle))
.ForEachEntity((Entity entity, Position position, Circle circle) => {
/* Draw Circle */
});
}
}
public class DrawRectangleSystem
{
public void OnUpdate()
{
ComponentQuery
.SelectReadOnly(typeof(Position), typeof(Rectangle))
.ForEachEntity((Entity entity, Position position, Rectangle rectangle) => {
/* Draw Rectangle */
});
}
}
Итак, если у вас был следующий формат данных:
Entity 1: [Position, Circle]
Entity 2: [Position, Circle]
Entity 3: [Position, Rectangle]
DrawCircleSystem
будет выполняться только для объектов 1 и 2, а DrawRectangleSystem
будет выполняться только для объекта 3. Таким образом, полиморфизм достигается за счет возможности запросов этих систем.
Такое программирование намного производительнее, чем ООП. Но помимо этого, это также делает наш код более масштабируемым и оптимизируемым. Например, если вы хотите реализовать отбраковку, чтобы на самом деле отображались только те сущности, которые находятся в представлении, мы можем легко сделать это с очень небольшими усилиями по рефакторингу. Все, что нам нужно сделать, это ввести новую систему, которая обрабатывает отсечение путем добавления или удаления нового компонента с именем Visible
для объектов, которые мы хотим нарисовать:
public struct Visible { }
public class CircleCullingSystem
{
public void OnUpdate()
{
// Give me all Circle entities that are NOT Visible
ComponentQuery
.SelectReadOnly(typeof(Position), typeof(Ciricle))
.Exclude(typeof(Visible))
.ForEachEntity((Entity entity, Position position, Circle circle) => {
// Add 'Visible' component to entity if it's within view range
});
// Give me all Circle entities that are Visible
ComponentQuery
.SelectReadOnly(typeof(Position), typeof(Ciricle))
.FilterBy(typeof(Visible))
.ForEachEntity((Entity entity, Position position, Circle circle) => {
// Remove 'Visible' component from entity if it's out of view range
});
}
}
А затем мы просто обновляем наш запрос в DrawCirlceSystem
, чтобы он фильтровался по компоненту Visible
:
public class DrawCirlceSystem
{
public void OnUpdate()
{
// Process all visible circle entities
ComponentQuery
.SelectReadOnly(typeof(Position), typeof(Circle))
.FilterBy(typeof(Visible))
.ForEachEntity((Entity entity, Position position, Circle circle) => {
/* Draw Circle */
});
}
}
И, конечно, нам нужно будет создать RectangleCullingSystem
, похожий на наш CircleCullingSystem
, поскольку поведение прямоугольников при отсечении отличается от кругов.
person
Vakey
schedule
01.02.2019