类设计:公共构造函数或私有静态工厂和COM对象

时间:2009-04-19 22:59:21

标签: c# constructor

我有点类设计问题。我将概述我正在考虑的三种模式。

示例1:

Class MyObject
{
    public MyObject(IWrapper wrapper,string name)
    {//set properties.}

    public Void Declare()
    {
        //Some COM stuff with IWrapper
     } 
}

使用

MyObject testobj = new MyObject(fakewrapper,"test");
testobj.Declare();

示例2:

Class MyObject
{
    public MyObject(IWrapper wrapper,string name)
    { //set properties.}

    public MyObject Declare()
    {
        //Some COM stuff with IWrapper
        return this;
     } 
}

使用

MyObject testobj = new MyObject(fakewrapper,"Test");
testobj = testobj.Declare();

示例3:使用私有构造函数

Class MyObject
{
    private MyObject(IWrapper wrapper,string name)
    {//set properties.}

    public static MyObject Declare(IWrapper wrapper,string name)
    {
        //Some COM stuff with IWrapper
        return new MyObject(wrapper,name);
     } 
}

使用

MyObject testobj = MyObject.Declare(fakewrapper,"Test");

我的主要问题是; 您认为哪一个更好的设计?
隐藏构造函数以支持静态工厂方法是不好的做法吗?

我也试图让它尽可能地变得可测试。 我似乎无法下定决心的唯一原因是因为MyObject类是COM应用程序中另一个对象的包装器。

问题是这个对象必须在COM应用程序中声明,这是声明方法在调用任何其他方法之前所做的事情,但是如果我隐藏构造函数然后添加更多使用Declare方法,我认为它会使类的其余部分难以测试,因为我必须首先通过Declare方法。

干杯。

1 个答案:

答案 0 :(得分:1)

选项3对我来说似乎是最干净的API。如果在调用Declare之前无法真正使用MyObject,那么将new和Declare包装到工厂方法中是有意义的,以确保类的用户在没有首先调用Declare的情况下不尝试使用MyObject。工厂方法也有助于维护道路。

帮助测试性的一种方法可能是将Declare操作包装在类中的可插入“IDeclarer”接口中。您的生产应用程序将使用调用COM应用程序的IDeclarer实现,而您的测试代码可以插入模拟IDeclarer。也许这样的事情(你可能不得不调整一下......):

class MyObject
{
    public IDeclarer Declarer { get; set; }

    private MyObject(IWrapper wrapper,string name)
    {
        // set properties
    }

    public static MyObject Declare(IWrapper wrapper,string name)
    {
        //Some COM stuff with IWrapper
        MyObject newMyObject = new MyObject(wrapper,name);
        return Declarer.Declare(newMyObject);
    } 
}

public interface IDeclarer
{
    MyObject Declare(MyObject obj);
}

public class ComDeclarer : IDeclarer
{
    public MyObject Declare(MyObject obj)
    {
        // do COM work
        return comObj;
    }
}

public class TestDeclarer : IDeclarer
{
    public MyObject Declare(MyObject obj)
    {
        // do nothing... or whatever
        return testObj;
    }
}