Как ответил @Oded, недостаток использования директив во время компиляции заключается в том, что вам необходимо скомпилировать конкретный двоичный файл для каждой платформы. Положительным моментом является то, что у вас нет раздутого универсального приложения, которое больше и медленнее на каждой платформе только потому, что оно не зависит от платформы.
Еще одним недостатком #if является то, что многие инструменты Visual Studio рассматривают только «текущий активный» код. Например, средства Intellisense и инструменты рефакторинга - если вы захотите переименовать IScreen в IDisplay, то вы обнаружите, что рефакторинг сработал, и весь код вашего ПК был обновлен безупречно, но весь ваш код Mac был бы сильно поврежден, поскольку инструменты рефакторинга просто не смогли бы » смотрите "другую ветку кода". Точно так же легко внести изменения в код в ветке ПК и забыть внести соответствующее изменение в ветку Mac, снова нарушив его.
Преимущество фабрики вместо "#if" заключается в том, что один двоичный образ потенциально может быть запущен на каждой платформе, и вам нужно проверять платформу хоста только один раз при создании конкретной реализации (так что она все еще очень эффективна в время выполнения, но будет больше, поскольку вам нужно будет отправить все варианты платформы в одном дистрибутиве)
Однако, можно получить лучшее из обоих миров, используя более модульный шаблон проектирования вместо #if: используйте спутниковую сборку для реализаций для конкретной платформы. При таком подходе основной код приложения будет указывать интерфейс IScreen
, и тогда у вас будут классы Concrete Screen
(Mac) и Screen
(PC) в отдельных зависящих от платформы вариантах Сборка ScreenImplementation.dll. Вы также можете отправить один установщик, который охватывает все платформы (просто развернув соответствующий сателлитный dll для хост-платформы). Это дает вам незначительное улучшение эффективности / размера при использовании #if, но без необходимости путать ваш код с условными выражениями. (Конечно, этот модульный подход имеет смысл как для конструкций #if, так и для Factory - они становятся скорее вариантом развертывания, чем архитектурой базовой реализации, когда вы разделяете реализации для конкретной платформы на отдельные сборки)