使用策略从超类创建子类
Using strategy to create subclasses from superclasses
我有一个 C#/OO/Design 相关问题。
我正在重新设计一个移植到 C# 的旧系统。我们正在重构系统,使其更简单、更面向对象。
在这个系统中,我们有各种与我们的业务领域相关的对象——文件夹、文档、用户、约会、任务等。所有这些对象都继承自一个名为 BaseObject 的基础对象,信不信由你:
public class BaseObject {
public int Id { get; set; }
public string Name { get; set; }
}
这个对象不是抽象的,因为我们实际上为一些简单的列表实例化了它。
我们也有自己的通用列表:
public class CustomList<T> : IENumerable<T> where T : BaseObject {
//... several properties and methods
}
}
我的问题是:我有许多继承自 BaseObject 的对象。例如,我可以创建一个 CustomList<User>
因为 User : BaseObject
.
然而,我的许多用户控件 return CustomList<BaseObject>
,仅仅是因为这是大多数基于列表的用户控件 CAN return:他们知道每个对象的名称,因为这就是他们的名字显示,他们使用它的 Id 作为键。
因此,我希望能够将 CustomList<BaseObject>
中的项目添加到任何 CustomList<T>
中。我希望能够添加对象,而不仅仅是构造一个新列表。
但是因为我不能只是从 superclass (BaseObject) 转换为 subclass (例如 User),所以我考虑在 [=17= 中实现以下方法]:
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
foreach (var item in items)
{
var newObject = constructor(item);
Add(newObject);
}
}
或者换句话说,如果 class 需要从 CustomList 创建一个 CustomList,它需要同时提供 CustomList 和一个方法,说明如何从 BaseObject 构造 T 的每个新实例,以及如何初始化 BaseObject 不知道的其他成员。
我认为这类似于策略模式。当然方法本身几乎没有什么代码,但是由于这个动作的普遍性,这样设计还是比较短的。
问题是 - 这是好的设计吗?是否有更好的模式来处理将对象的简化版本从 UI 移动到实际对象的情况?
基本上您已经实现了某种类似于 Linq 的 Select
函数的 map 函数。现在很多人更喜欢函数式风格而不是普通的老式 OOP。您的 AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
是您想要做的事情的简单明了的方法。
另一种使用 Linq 的方法可能是
public static CustomList<T> ToCustomList<T>(this IEnumerable<T> items)
where T : BaseObject
{
var customList = new CustomList<T>();
foreach(var item in items)
customList.Add(item);
}
然后像
一样使用它
IEnumerable<BaseObject> items = ...;
Func<BaseObject, T> constructor = ...;
// Usage would be
CustomList<T> customItems =
(from i in items
select constructor).ToCustomList();
// or
CustomList<T> customItems = items.Select(constructor).ToCustomList();
不创建新列表
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
// AddRange from List<T>
AddRange(items.Select(constructor);
}
我有一个 C#/OO/Design 相关问题。
我正在重新设计一个移植到 C# 的旧系统。我们正在重构系统,使其更简单、更面向对象。
在这个系统中,我们有各种与我们的业务领域相关的对象——文件夹、文档、用户、约会、任务等。所有这些对象都继承自一个名为 BaseObject 的基础对象,信不信由你:
public class BaseObject {
public int Id { get; set; }
public string Name { get; set; }
}
这个对象不是抽象的,因为我们实际上为一些简单的列表实例化了它。
我们也有自己的通用列表:
public class CustomList<T> : IENumerable<T> where T : BaseObject {
//... several properties and methods
}
}
我的问题是:我有许多继承自 BaseObject 的对象。例如,我可以创建一个 CustomList<User>
因为 User : BaseObject
.
然而,我的许多用户控件 return CustomList<BaseObject>
,仅仅是因为这是大多数基于列表的用户控件 CAN return:他们知道每个对象的名称,因为这就是他们的名字显示,他们使用它的 Id 作为键。
因此,我希望能够将 CustomList<BaseObject>
中的项目添加到任何 CustomList<T>
中。我希望能够添加对象,而不仅仅是构造一个新列表。
但是因为我不能只是从 superclass (BaseObject) 转换为 subclass (例如 User),所以我考虑在 [=17= 中实现以下方法]:
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
foreach (var item in items)
{
var newObject = constructor(item);
Add(newObject);
}
}
或者换句话说,如果 class 需要从 CustomList 创建一个 CustomList,它需要同时提供 CustomList 和一个方法,说明如何从 BaseObject 构造 T 的每个新实例,以及如何初始化 BaseObject 不知道的其他成员。
我认为这类似于策略模式。当然方法本身几乎没有什么代码,但是由于这个动作的普遍性,这样设计还是比较短的。
问题是 - 这是好的设计吗?是否有更好的模式来处理将对象的简化版本从 UI 移动到实际对象的情况?
基本上您已经实现了某种类似于 Linq 的 Select
函数的 map 函数。现在很多人更喜欢函数式风格而不是普通的老式 OOP。您的 AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
是您想要做的事情的简单明了的方法。
另一种使用 Linq 的方法可能是
public static CustomList<T> ToCustomList<T>(this IEnumerable<T> items)
where T : BaseObject
{
var customList = new CustomList<T>();
foreach(var item in items)
customList.Add(item);
}
然后像
一样使用它IEnumerable<BaseObject> items = ...;
Func<BaseObject, T> constructor = ...;
// Usage would be
CustomList<T> customItems =
(from i in items
select constructor).ToCustomList();
// or
CustomList<T> customItems = items.Select(constructor).ToCustomList();
不创建新列表
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
// AddRange from List<T>
AddRange(items.Select(constructor);
}