1

这是一个通用的软件设计问题。

使用#if 编译器指令来支持多个平台是否是个好主意。例如,我有三个文件:

IScreen.cs

public interface IScreen {
   ...
}

ScreenWin.cs

#if WIN

public class Screen : IScreen {
  ...
}

#endif

ScreenMac.cs

#if WIN

public class Screen : IScreen {
   ...
}

#endif

看起来很酷的是我可以使用 BDD 并拥有类似的东西:

Given a Screen exists with width: 1920 and height: 1080

并且将根据编译器指令使用正确的屏幕。

与尝试使用抽象工厂相比,这似乎也可以获得更好的性能。

有哪些缺点?

4

2 回答 2

2

正如@Oded 所回答的那样,使用编译时指令的缺点是您必须为每个平台编译一个特定的二进制文件。好的一面是,你没有一个臃肿的、万能的应用程序,它在每个平台上都更大、更慢,只是因为它是平台独立的。

#if 的另一个缺点是许多 Visual Studio 工具只考虑“当前活动”的代码。例如,智能感知和重构工具 - 如果您希望将 IScreen 重命名为 IDisplay,那么您会发现重构工作并且您的所有 PC 代码都已完美更新,但您的所有 Mac 代码将被严重破坏,因为重构工具根本不会“见”另一个代码分支。同样,很容易对 PC 分支上的代码进行更改而忘记对 Mac 分支进行相应的更改,从而再次破坏它。

工厂而不是“#if”的好处是单个二进制映像可以在每个平台上运行,并且您只需要在创建具体实现时检查一次主机平台(因此它在运行时仍然非常有效,但是会更大,因为您必须在一个发行版中运送所有平台变体)

但是,可以通过使用更模块化的设计模式而不是#if 来获得两全其美:使用卫星程序集进行平台特定的实现。在这种方法中,主应用程序代码将指定IScreen interface,然后您将拥有 Concrete Screen(Mac) 和ScreenScreenImplementation.dll 程序集的不同平台特定变体中的 (PC) 类。您还可以发布一个涵盖所有平台的安装程序(只需为主机平台部署适当的附属 dll)。这为您提供了使用 #if 的边际效率/大小改进,但实际上不必用条件来弄乱您的代码。(当然,这种模块化方法对#if 和 Factory 设计都有意义——一旦将特定于平台的实现拆分为单独的程序集,它们就更像是一种部署选项,而不是核心实现架构)

于 2011-03-26T21:58:54.233 回答
1

缺点包括必须编译多个二进制文件——每个平台一个。

如果不小心,您最终可能会在代码的许多部分中使用预处理器指令使您的代码混乱。请参阅有关反转一个这样的代码库的这个SO 问题。

如果您可以在代码中检测平台,这是一种更好的方法。

于 2011-03-26T20:41:40.370 回答