工厂方法实现的含义

本文关键字:实现 方法 工厂 | 更新日期: 2023-09-27 18:12:56

首先,这是一个严格的c#问题!请将您的知识限制为c#。

在一个应用程序我正在工作,我们有一些类,我们提供预设的"原型"。在非常高的级别:

public class Foo
{
    #region Variables / Properties
    public bool Bar { get; set; }
    public string Name { get; set; }
    public int Fooby { get; set; }
    #endregion Variables / Properties
    #region Prototypes
    public Foo SomePrototype = new Foo
    {
        Bar = false,
        Name = "Generic False State",
        Fooby = -1
    };
    public Foo SomeOtherPrototype = new Foo
    {
        Bar = true,
        Name = "Generic True State",
        Fooby = Int32.MaxValue
    };
    #endregion Prototypes
    #region Methods
    // ...Behaviors here.
    #endregion Methods
}

注意"原型"部分。我一直都明白,在c#中,做这种"原型"的"正确"方法是:

public Foo SomePrototype
{
    get 
    { 
        return new Foo
        {
            Bar = false,
            Name = "Generic False State",
            Fooby = -1
        };
    }
}

虽然我猜"原型"实现都可以工作,问题:我在我们的代码库(即第一个示例)中看到的方式的一些含义是什么?

对我来说,明显的含义是"原型"的所有用法都只是对面向公众的Foo变量的引用,这可以提供一些有趣的交互……我只是想知道是否还有更多需要注意的

工厂方法实现的含义

这两段代码并不是同一件事的不同实现,而是服务于不同的目的:

  • #1给出了类似于"实例单例"的东西…从单个Foo实例导出的所有Someprototype都是参考相等的。如果您从不更改内存,那么保存内存非常好。
  • #2为每个调用提供一个独立的实例。很好,如果你需要修改它们。

在你的例子中有一些不同之处(从技术角度来看,这与原型设计无关,但与c#有关):

  • 示例1:使用一次创建实例的公共可写字段。
  • 示例2:使用公共只读属性,每次调用创建一个实例。

那么,有什么不同呢?

  • Foo不是不可变的。因此程序可以在代码中的多个位置修改原型。在示例1的情况下,这会修改所有其他代码使用的原型(foo.SomePrototype.Fooby = -1),这可能是不希望的。
  • public字段是可写的,因此程序可以修改对原型(foo.SomePrototype = new Foo {...})的引用,这对使用该原型的其他代码有影响。突然之间原型机就可以被替换了。

现在关于原型:

  • 如果你看一下原型模式(http://en.wikipedia.org/wiki/Prototype_pattern),它只是说明原型应该被用来创建它的一个新的克隆。
  • 阅读这篇文章,您可以看到客户端负责创建克隆,而不是类本身。拥有一个原型意味着你有一个实例,并创建它的许多副本。您的属性每次调用都会创建新实例。
  • 实际上你正在使用工厂方法模式。嗯…它是一个属性,但每次你调用它时,它仍然会创建一个对象。
  • 在我看来,我会选择每次调用返回相同引用的a属性。引用存储在私有(非公共)字段中。

的例子:

public class Foo  
{  
    #region Variables / Properties
    public bool Bar { get; set; }
    public string Name { get; set; }
    public int Fooby { get; set; }
    #endregion Variables / Properties
    #region Prototypes
    static private Foo _SomePrototype = new Foo
    {
        Bar = false,
        Name = "Generic False State",
        Fooby = -1
    };
    static private Foo _SomeOtherPrototype = new Foo
    {
        Bar = true,
        Name = "Generic True State",
        Fooby = Int32.MaxValue
    };
    static public Foo SomePrototype 
    {
        get
        {
            return _SomePrototype;
        }
    }
    static public Foo SomeOtherPrototype 
    {
        get
        {
            return _SomeOtherPrototype;
        }
    }
    #endregion
}

要回答这个问题:你想用什么模式?是样板还是工厂样板?

含义非常直接:第一个实现将潜在的"原型"转换为"单例"。正如您正确指出的那样,使用这种原型的所有东西都必须使用相同的实例。这是不可取的,因为实例是可变的。表示一般的false和true状态的两个对象将是非常好的单例候选对象,但是您应该使它们不可变,或者通过只读接口表示它们:

interface IFoo {
    bool Bar { get; }
    string Name { get; }
    int Fooby { get; }
}
public class Foo : IFoo {
    ...
    public static readonly IFoo SomePrototype = new Foo
    {
        Bar = false,
        Name = "Generic False State",
        Fooby = -1
    };
    public static readonly IFoo SomeOtherPrototype = new Foo
    {
        Bar = true,
        Name = "Generic True State",
        Fooby = Int32.MaxValue
    };
    ...
}