如何正确使用构图?
How to use composition correctly?
[DataContract(Name = "jobDateTimeFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobDateTimeFilterRequest : TimeFrame
{
[DataMember(Name = "jobType")]
public BackgroundJobType JobType { get; set; }
}
[DataContract(Name = "timeFrame", Namespace = Constants.ManagementNamespace)]
public class TimeFrame
{
[DataMember(Name = "from")]
public DateTime From { get; set; }
[DataMember(Name = "to")]
public DateTime To { get; set; }
}
我想使用组合而不是继承。
为此,我需要创建:
[DataContract(Name = "jobFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobFilterRequest
{
[DataMember(Name = "jobType")]
public BackgroundJobType JobType { get; set; }
}
而JobDateTimeFilterRequest
会是这样的:
[DataContract(Name = "jobDateTimeFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobDateTimeFilterRequest
{
[DataMember(Name = "jobType")]
public JobFilterRequest JobFilter { get; set; }
[DataMember(Name = "timeFrame")]
public TimeFrame TimeFrame{ get; set; }
}
我说的对吗?还是对构图的理解不正确?
总的来说你是对的。您已将基础 class 的实例置于派生 class 的状态。但是你不应该忘记封装,在当前的实现中,可能会得到 JobDateTimeFilterRequest
对象的不一致状态,例如通过设置 TimeFrame
null。考虑一下它依赖于业务逻辑的对象的一致状态。我不知道你的业务逻辑,但你的案例可以通过使用 TimeFrame
属性 的私有 setter 的构造函数参数来完成。请注意,我们正在谈论一般情况,但有 WCF
逻辑可能会被 private
修饰符
破坏
大概是这样的(我忽略WCF
属性和逻辑):
public class JobDateTimeFilterRequest
{
public JobFilterRequest JobFilter { get; set; }
public TimeFrame TimeFrame{ get; private set; }
public JobDateTimeFilterRequest(TimeFrame timeFrame)
{
this.TimeFrame = timeFrame;
}
}
"composition over inheritance"原则通常适用于具有行为的对象,而不是简单的数据结构。原因是,使用新 功能 可以更轻松地扩展系统。相反,仅仅引入新数据并不会改变系统本身。
在你的情况下,只要你不覆盖属性并且它们仍然是 public 自动属性,从 TimeFrame
继承可能和拥有 [=10] 一样好=].
[DataContract(Name = "jobDateTimeFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobDateTimeFilterRequest : TimeFrame
{
[DataMember(Name = "jobType")]
public BackgroundJobType JobType { get; set; }
}
[DataContract(Name = "timeFrame", Namespace = Constants.ManagementNamespace)]
public class TimeFrame
{
[DataMember(Name = "from")]
public DateTime From { get; set; }
[DataMember(Name = "to")]
public DateTime To { get; set; }
}
我想使用组合而不是继承。 为此,我需要创建:
[DataContract(Name = "jobFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobFilterRequest
{
[DataMember(Name = "jobType")]
public BackgroundJobType JobType { get; set; }
}
而JobDateTimeFilterRequest
会是这样的:
[DataContract(Name = "jobDateTimeFilterRequest", Namespace = Constants.ManagementNamespace)]
public class JobDateTimeFilterRequest
{
[DataMember(Name = "jobType")]
public JobFilterRequest JobFilter { get; set; }
[DataMember(Name = "timeFrame")]
public TimeFrame TimeFrame{ get; set; }
}
我说的对吗?还是对构图的理解不正确?
总的来说你是对的。您已将基础 class 的实例置于派生 class 的状态。但是你不应该忘记封装,在当前的实现中,可能会得到 JobDateTimeFilterRequest
对象的不一致状态,例如通过设置 TimeFrame
null。考虑一下它依赖于业务逻辑的对象的一致状态。我不知道你的业务逻辑,但你的案例可以通过使用 TimeFrame
属性 的私有 setter 的构造函数参数来完成。请注意,我们正在谈论一般情况,但有 WCF
逻辑可能会被 private
修饰符
大概是这样的(我忽略WCF
属性和逻辑):
public class JobDateTimeFilterRequest
{
public JobFilterRequest JobFilter { get; set; }
public TimeFrame TimeFrame{ get; private set; }
public JobDateTimeFilterRequest(TimeFrame timeFrame)
{
this.TimeFrame = timeFrame;
}
}
"composition over inheritance"原则通常适用于具有行为的对象,而不是简单的数据结构。原因是,使用新 功能 可以更轻松地扩展系统。相反,仅仅引入新数据并不会改变系统本身。
在你的情况下,只要你不覆盖属性并且它们仍然是 public 自动属性,从 TimeFrame
继承可能和拥有 [=10] 一样好=].