Interface 对于跨平台实现,我应该使用接口还是工厂(和接口)?
示例A:Interface 对于跨平台实现,我应该使用接口还是工厂(和接口)?,interface,cross-platform,factory,Interface,Cross Platform,Factory,示例A: // pseudo code interface IFoo { void bar(); } class FooPlatformA : IFoo { void bar() { /* ... */ } } class FooPlatformB : IFoo { void bar() { /* ... */ } } class Foo : IFoo { IFoo m_foo; public Foo() { if (detectPl
// pseudo code
interface IFoo {
void bar();
}
class FooPlatformA : IFoo {
void bar() { /* ... */ }
}
class FooPlatformB : IFoo {
void bar() { /* ... */ }
}
class Foo : IFoo {
IFoo m_foo;
public Foo() {
if (detectPlatformA()} {
m_foo = new FooPlatformA();
} else {
m_foo = new FooPlatformB();
}
}
// wrapper function - downside is we'd have to create one
// of these for each function, which doesn't seem right.
void bar() {
m_foo.bar();
}
}
Main() {
Foo foo = new Foo();
foo.bar();
}
例B:
// pseudo code
interface IFoo {
void bar();
}
class FooPlatformA : IFoo {
void bar() { /* ... */ }
}
class FooPlatformB : IFoo {
void bar() { /* ... */ }
}
class FooFactory {
IFoo newFoo() {
if (detectPlatformA()} {
return new FooPlatformA();
} else {
return new FooPlatformB();
}
}
}
Main() {
FooFactory factory = new FooFactory();
IFoo foo = factory.newFoo();
foo.bar();
}
哪一个是更好的选择,例如A、B、NOTE或“它取决于”?A的问题是您必须在Foo中实现IFoo的每个方法。如果只有一对夫妇,这不是什么大不了的事,但是如果有几十对夫妇,那就是一种痛苦。如果您使用的是支持工厂方法的语言,如Curl,则可以在IFoo中放置工厂方法:
{define-class abstract IFoo
{method abstract {bar}:void}
{factory {default}:{this-class}
{if platformA? then
{return {FooPlatformA}}
else
{return {FooPlatformB}}
}
}
}
{define-class FooPlatformA {inherits IFoo}
{method {bar}:void}
}
...
def foo = {IFoo}
{foo.bar}
当可能存在单个功能集的多个实现时,使用接口。这听起来好像适用于您的特定场景 就你的例子而言,我肯定会使用B,它更容易维护。A在单个类[和/或方法]中嵌入了太多的公共逻辑[ie平台检测]。如果要构建自己的工厂类,请尝试[通过泛型的
Resolve()
方法或其他方法]对其进行泛化,而不是每个接口使用方法\类
比如说,
// i called it a "container" because it "contains" implementations
// or instantiation methods for requested types - but it *is* a
// factory.
public class Container
{
// "resolves" correct implementation for a requested type.
public IType Resolve<IType> ()
{
IType typed = default (IType);
if (isPlatformA)
{
// switch or function map on IType for correct
// platform A implementation
}
else if (isPlatformB)
{
// switch or function map on IType for correct
// platform B implementation
}
else
{
// throw NotSupportedException
}
return typed;
}
}
//我称它为“容器”,因为它“包含”实现
//或者请求类型的实例化方法,但它是
//工厂。
公营货柜
{
//“解析”请求类型的正确实现。
公共IType解析()
{
IType typed=默认值(IType);
if(iPlatforma)
{
//IType上的开关或功能映射是否正确
//平台A实现
}
else if(iPlatformb)
{
//IType上的开关或功能映射是否正确
//B平台实施
}
其他的
{
//抛出NotSupportedException
}
返回类型;
}
}
但是,您可能希望研究替代实现,例如MS或Castle Windsor,而不是实现自己的工厂模式。它们易于配置和使用
理想情况下
// use an interface to isolate *your* code from actual
// implementation, which could change depending on your needs,
// for instance if you "roll your own" or switch between Unity,
// Castle Windsor, or some other vendor
public interface IContainer
{
IType Resolve<IType> ();
}
// custom "roll your own" container, similar to above,
public class Container : IContainer { }
// delegates to an instance of a Unity container,
public class UnityContainer : IContainer { }
// delegates to an instance of a CastleWindsorContainer,
public class CastleWindsorContainer : IContainer { }
//使用接口将*您的*代码与实际代码隔离开来
//实施,根据您的需要可能会有所变化,
//例如,如果你“自己滚”或在统一之间切换,
//温莎城堡或其他供应商
公共接口IContainer
{
IType解析();
}
//自定义“滚动您自己的”容器,与上面类似,
公共类容器:IContainer{}
//委托给Unity容器的实例,
公共类UnityContainer:IContainer{}
//委托给CastleWindsorContainer的实例,
公共类CastleWindsorContainer:IContainer{}
哦,我想我也应该对他大声喊叫。我只是对Unity或CastleWindsor不太熟悉。如果你问我B更好——因为Foo本身不需要在平台上进行任何切换。这有什么关系?好吧,因为你可能想分别测试所有组件——使用“测试”IFoo的Foo,在平台a上分别测试FooPlatformA,在平台B上分别测试FooPlatformB。如果你在Foo中坚持选择,你需要在a和B上测试Foo,而不仅仅是在不同的IFoo上。无明显原因地使组件更耦合。我想说,您的显式出厂选项(选项B)通常更好 在第一个示例中,Foo类有效地完成了两个任务,一个是工厂,另一个是代理。两份工作,一门课,让我感到不安
您的第二个选项让客户承担了更多的责任:他们需要知道如何使用工厂,但这是一个广泛使用的习惯用法,我认为不难理解。工厂是一个更干净的解决方案,因为您没有在包装器
类Foo:IFoo
中实现接口的每个成员。想象一下,每次修改IFoo接口时,都需要更新包装器。在编程时,根据您的目标,尽量考虑可维护性。
是所有“平台”都可用,还是只有一个?平台之间的唯一区别是逻辑吗?从游戏开发者的角度考虑,我会使用#defines来实现这一点
class Platform : IPlatform
{
void Update()
{
#if PLATFORM_A
* ... Logic for platform A */
#elif PLATFORM_B
* ... Logic for platform A */
#endif
}
}
HTH,有趣的答案,不过我使用的是C#,但工厂确实仍然是一种选择。我想知道在这种情况下使用工厂是否有明显的缺点;我知道使用Foo,Bar,FooBar是一种常见的编程范例,但老实说,为了理解您的意图,必须多次阅读您的示例|回答得很好。老实说,有4个功能让我感到很不舒服。我们正在将我的代理/包装器/工厂模型重新实现为一个干净的工厂。请注意,您能否在synergy中对CArch类发表评论(它演示了类似于示例a的内容):谢谢。我认为这个例子非常关注于创建代理。从客户的角度来看,使用了一个简单的体系结构对象,我们正在努力创建这些代理方法,以简化客户的生活。工厂方法很简单。如果我们开始有工厂逻辑的许多变体,特别是如果我们能从抽象工厂模式中获益,那么我更愿意重构工厂代码。现在,我们最重视客户机的简单性。