Функция двойного шанса - Double-chance function
В программная инженерия, а функция двойного шанса это программное обеспечение шаблон дизайна с сильным применением в кросс-платформенный и масштабируемая разработка.
Рассмотрим графику API с функциями для DrawPoint
, DrawLine
, и DrawSquare
. Легко заметить, что DrawLine
могут быть реализованы исключительно в рамках DrawPoint
, и DrawSquare
в свою очередь может быть реализовано посредством четырех обращений к DrawLine
. Если бы вы переносили этот API на новую архитектуру, у вас был бы выбор: реализовать три разные функции изначально (для реализации потребуется больше времени, но, вероятно, приведет к более быстрому коду) или написать DrawPoint
изначально, а остальные реализовать, как описано выше, с использованием общего кроссплатформенного кода. Важным примером такого подхода является X11 графическая система, которая может быть перенесена на новое графическое оборудование, предоставляя очень небольшое количество зависимых от устройства примитивов, оставляя функции более высокого уровня аппаратно-независимому уровню.[1][2]
Функция двойного шанса - это оптимальный метод создания такой реализации, при котором первый черновик порта может использовать версию «быстро выводить на рынок, медленно запускать» с общим DrawPoint
функция, в то время как более поздние версии могут быть изменены как «медленно выводить на рынок, быстро запускать». Шаблон двойного шанса имеет высокие оценки, так как базовый API включает самоподдерживающуюся реализацию, данную здесь как часть нулевого драйвера, а все другие реализации являются его расширениями. Следовательно, первый порт фактически является первой используемой реализацией.
Одна типичная реализация в C ++ может быть:
учебный класс CBaseGfxAPI { виртуальный пустота DrawPoint(int Икс, int у) = 0; / * Абстрактная концепция для нулевого драйвера * / виртуальный пустота DrawLine(int x1, int y1, int x2, int y2) { / * DrawPoint () повторяется * /} виртуальный пустота DrawSquare(int x1, int y1, int x2, int y2) { / * DrawLine () повторяется * /} }; учебный класс COriginalGfxAPI : общественный CBaseGfxAPI { виртуальный пустота DrawPoint(int Икс, int у) { / * Единственные необходимые нативные вызовы * / } виртуальный пустота DrawLine(int x1, int y1, int x2, int y2) { / * Если эта функция существует, собственный DrawLine будет использоваться рутина. В противном случае база реализация запущена. * /} }; учебный класс CNewGfxAPI : общественный CBaseGfxAPI { виртуальный пустота DrawPoint(int Икс, int у) { / * Единственное, что нужно для нативных вызовов * / } };
Обратите внимание, что CBaseGfxAPI :: DrawPoint
Функция никогда не используется сама по себе, поскольку любой графический вызов проходит через один из ее производных классов. Итак, призыв к CNewGfxAPI :: DrawSquare
получит свой первый шанс отобразить квадрат CNewGfxAPI
учебный класс. Если нативной реализации не существует, то вызывается базовый класс, после чего виртуализация берет на себя и означает, что CNewGfxAPI :: DrawLine
называется. Это дает CNewGfxAPI
класс «второй шанс» использовать собственный код, если таковые имеются.
С помощью этого метода теоретически можно построить целый 3D-движок (применяя программного обеспечения растеризация) с использованием только одной встроенной функции в форме DrawPoint, а другие функции будут реализованы по мере того, как позволяет время. На практике это будет безнадежно медленным, но оно действительно демонстрирует возможности для функций с двойным шансом.
Рекомендации
- Гудвин, Стивен (2005). Кросс-платформенное программирование игр. Чарльз Ривер Медиа. ISBN 1-58450-379-3.