原型模式:确保克隆处于有效状态

时间:2015-10-01 20:02:29

标签: c# oop design-patterns prototype-pattern

LogEvent表示日志级别,消息,用户,进程名称等信息...... 其中一些属性'价值需要相当大的努力才能产生,例如: G。进程名称。那些属性'生成的值通常没有改变,但尽管如此,应该可以更改它们。

我认为原型模式以protoype开头,其泛型属性是预先分配的。原型在应用程序的生命周期内保持相同的对象,但其属性为'值可能会如上所述发生变化。新的LogEvent对象应使用当前原型的值,在更改之前使用旧值继续创建的对象,这意味着,引用来自" real" LogEvent对象不是一个选项。

然而,"真实" LogEvent要求某些属性不为null,而此要求对原型无用。我想防止LogEvent的无效对象。但是,如果我使用通常的原型模式,我将不得不添加一个构造函数来创建原型,但是这个构造函数不会创建一个有效的对象,我想避免使用无效的对象(原型本身或它的克隆)意外。

我花了一些时间来搜索解决方案,但下面列出的方法非常难看。我希望,有一个优雅的解决方案。同时我倾向于选择3,因为1和2看起来并不干净。

一般结构

List<TestClass>

选项1

赞成

  • LogEventPrototype不能用作ILogEvent。
  • 属性不必在多个类中声明

缺点

  • 属性必须手动映射
  • 静态方法=&gt;原型的界面不可能

代码

public interface ILogEvent
{
    string PreAllocatedProperty1 { get; set; }
    string PreAllocatedProperty2 { get; set; }
    string IndividualProperty1 { get; set; }
    string IndividualProperty2 { get; set; }
}

选项2

与选项1类似,但是:

赞成

  • 确保&#34;,LogEventPrototype永远不会被实例化,它只是用作返回类型
  • 无手动映射

缺点:看起来好像很黑。

class LogEventPrototype
{
    public string PreAllocatedProperty1 { get; set; }
    public string PreAllocatedProperty2 { get; set; }
    public string IndividualProperty1 { get; set; }
    public string IndividualProperty2 { get; set; }
    public LogEventPrototype() { GeneratePreAllocatedProperties(); }

    private void GeneratePreAllocatedProperties()
    {
        // if you invoke the helper functions later again, 
        // they might return different results (e. g.: user identity, ...)
        PreAllocatedProperty1 = Helper.ComplexFunction();
        PreAllocatedProperty2 = Helper.AnotherComplexFunction();
    }
}

class LogEvent : LogEventPrototype, ILogEvent
{
    // just for creating the prototype, object will be in an INVALID state
    private LogEvent() : base() { }
    // object will be in a VALID state
    public LogEvent(string individualProperty2)
        : this()
    {
        if (individualProperty2 == null)
            throw new ArgumentNullException();

        IndividualProperty2 = individualProperty2;
    }
    public static LogEvent FromPrototype(LogEventPrototype prototype)
    {
        // clone manually
        return new LogEvent(prototype.IndividualProperty2)
        {
            IndividualProperty1 = prototype.IndividualProperty1,
            PreAllocatedProperty1 = prototype.PreAllocatedProperty1,
            PreAllocatedProperty2 = prototype.PreAllocatedProperty2
        };
    }
}

选项3

不要将专用类用于原型,而是将LogEvent构造函数设置为public并冒无效的LogEvent对象。请改用Validate()方法,并希望客户端不要忘记使用它。

0 个答案:

没有答案