Interface 对于跨平台实现,我应该使用接口还是工厂(和接口)?

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

示例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 (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的内容):谢谢。我认为这个例子非常关注于创建代理。从客户的角度来看,使用了一个简单的体系结构对象,我们正在努力创建这些代理方法,以简化客户的生活。工厂方法很简单。如果我们开始有工厂逻辑的许多变体,特别是如果我们能从抽象工厂模式中获益,那么我更愿意重构工厂代码。现在,我们最重视客户机的简单性。