界面我如何获得任何客户?
Interface how do I get any Customer?
我们有一个与通用客户 (gold/silver) 的接口,现在假设我将最后创建的客户存储在某处 (Cache/DB/etc)。
如何创建 returns 客户类型的 GetCustomer 方法。
我应该将 GetCustomer 添加到基础 class 或接口或其他地方吗?以及我们如何使用 GetCustomer ?
希望这是有道理的。
interface ICstomerInterface<T>
{
T MakeCustomer();
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public string Type { get; set; }
public string Name { get; set; }
// methods
public abstract T MakeCustomer();
}
public class Gold : BaseCustomer<Gold>
{
public override Gold MakeCustomer()
{
var customer = new Gold
{
Type= "Gold",
Name = "Jack"
};
return customer;
}
}
public class Silver : BaseCustomer<Silver>
{
public override Silver MakeCustomer()
{
var customer = new Silver();
customer.Name = "Jones";
customer.Type = "Silver";
return customer;
}
}
您可以使用扩展方法来获取客户类型(在静态 class 上):
public static Type GetCustomerType<T>(this ICstomerInterface<T> _customer)
{
return typeof(T);
}
所有这些都是为了让您不必在每次创建实现该接口的新客户 class 时都编写冗余代码。
您似乎正在尝试使用 classic Factory Method。
就个人而言,对于简单的 classes,就像你问的那样,我会在基础 class 上添加一个静态方法,如下所示:
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public static BaseCustomer<T> GetLastCustomer()
{
// Get from storage, the last customer.
}
}
这样,您的创建客户方法与获取客户方法是分开的,但仍然可以从任何地方访问。
您的示例代码不包含可以包含所有客户的基本类型,即没有可以包含 BaseCustomer<Gold>
或 BaseCustomer<Silver>
的 strongly-typed 变量。这两者之间根本没有类型兼容性,最多 Dictionary<int>
可以存储为 Dictionary<string>
(事实上,更糟糕的是,因为你的对象模型中没有协方差)。鉴于这一事实,您的问题毫无意义,因为您总是必须声明类型参数以将客户存储在某处,因此无需在 运行 时间学习类型。
但是假设您想要一个同时适用于两者的缓存。您将引入一个 non-generic 基本接口:
public interface ICustomer
{
Guid CustomerGuid { get; }
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>, ICustomer
{
///etc....
现在您可以定义一个可以容纳所有客户的缓存:
var cache = new Dictionary<Guid,ICustomer>();
var gold = new Gold();
cache.Add( gold.CustomerGuid, gold );
var silver = new Silver();
cache.Add( silver.CustomerGuid, silver );
现在您可以通过其 Guid 检索任何客户:
var customer = cache[guid];
要确定它的类型,只需使用
bool isGold = customer is Gold;
bool isSilver = customer is Silver;
或者获取告诉您类型的字符串:
string type = customer.GetType().Name;
你设计的问题是MakeCustomer
是customers的一个实例方法。这意味着,您必须创建一个客户才能致电 MakeCustomer
。也就是说,这个设计是行不通的!
您有两个选择:要么简单地在各自的构造函数中初始化客户,要么创建一个客户工厂。这必须是一个单独的 class(静态或非静态)。
泛型类型参数是多余的。
public abstract class CustomerBase
{
public CustomerBase(string name)
{
Name = name;
}
public abstract string Type { get; }
public string Name { get; }
}
public class GoldCustomer : CustomerBase
{
public GoldCustomer(string name)
: base(name)
{
}
public override string Type => "Gold";
}
public class SilverCustomer : CustomerBase
{
public SilverCustomer(string name)
: base(name)
{
}
public override string Type => "Silver";
}
Type
属性只能是getter属性。它可以在基础 class 中进行抽象,以强制具体的客户 class 来实现它。
必须将名称传递给构造函数才能为不同的客户分配不同的名称。
另请参见维基百科上的 Abstract factory pattern。
示例:
var customers = new List<CustomerBase> {
new GoldCustomer("Frank"),
new SilverCustomer("Jack")
};
foreach (CustomerBase c in customers) {
Console.WriteLine($"{c.Name} is {c.Type}");
}
打印:
Frank is Gold
Jack is Silver
我们有一个与通用客户 (gold/silver) 的接口,现在假设我将最后创建的客户存储在某处 (Cache/DB/etc)。
如何创建 returns 客户类型的 GetCustomer 方法。 我应该将 GetCustomer 添加到基础 class 或接口或其他地方吗?以及我们如何使用 GetCustomer ?
希望这是有道理的。
interface ICstomerInterface<T>
{
T MakeCustomer();
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public string Type { get; set; }
public string Name { get; set; }
// methods
public abstract T MakeCustomer();
}
public class Gold : BaseCustomer<Gold>
{
public override Gold MakeCustomer()
{
var customer = new Gold
{
Type= "Gold",
Name = "Jack"
};
return customer;
}
}
public class Silver : BaseCustomer<Silver>
{
public override Silver MakeCustomer()
{
var customer = new Silver();
customer.Name = "Jones";
customer.Type = "Silver";
return customer;
}
}
您可以使用扩展方法来获取客户类型(在静态 class 上):
public static Type GetCustomerType<T>(this ICstomerInterface<T> _customer)
{
return typeof(T);
}
所有这些都是为了让您不必在每次创建实现该接口的新客户 class 时都编写冗余代码。
您似乎正在尝试使用 classic Factory Method。
就个人而言,对于简单的 classes,就像你问的那样,我会在基础 class 上添加一个静态方法,如下所示:
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public static BaseCustomer<T> GetLastCustomer()
{
// Get from storage, the last customer.
}
}
这样,您的创建客户方法与获取客户方法是分开的,但仍然可以从任何地方访问。
您的示例代码不包含可以包含所有客户的基本类型,即没有可以包含 BaseCustomer<Gold>
或 BaseCustomer<Silver>
的 strongly-typed 变量。这两者之间根本没有类型兼容性,最多 Dictionary<int>
可以存储为 Dictionary<string>
(事实上,更糟糕的是,因为你的对象模型中没有协方差)。鉴于这一事实,您的问题毫无意义,因为您总是必须声明类型参数以将客户存储在某处,因此无需在 运行 时间学习类型。
但是假设您想要一个同时适用于两者的缓存。您将引入一个 non-generic 基本接口:
public interface ICustomer
{
Guid CustomerGuid { get; }
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>, ICustomer
{
///etc....
现在您可以定义一个可以容纳所有客户的缓存:
var cache = new Dictionary<Guid,ICustomer>();
var gold = new Gold();
cache.Add( gold.CustomerGuid, gold );
var silver = new Silver();
cache.Add( silver.CustomerGuid, silver );
现在您可以通过其 Guid 检索任何客户:
var customer = cache[guid];
要确定它的类型,只需使用
bool isGold = customer is Gold;
bool isSilver = customer is Silver;
或者获取告诉您类型的字符串:
string type = customer.GetType().Name;
你设计的问题是MakeCustomer
是customers的一个实例方法。这意味着,您必须创建一个客户才能致电 MakeCustomer
。也就是说,这个设计是行不通的!
您有两个选择:要么简单地在各自的构造函数中初始化客户,要么创建一个客户工厂。这必须是一个单独的 class(静态或非静态)。
泛型类型参数是多余的。
public abstract class CustomerBase
{
public CustomerBase(string name)
{
Name = name;
}
public abstract string Type { get; }
public string Name { get; }
}
public class GoldCustomer : CustomerBase
{
public GoldCustomer(string name)
: base(name)
{
}
public override string Type => "Gold";
}
public class SilverCustomer : CustomerBase
{
public SilverCustomer(string name)
: base(name)
{
}
public override string Type => "Silver";
}
Type
属性只能是getter属性。它可以在基础 class 中进行抽象,以强制具体的客户 class 来实现它。
必须将名称传递给构造函数才能为不同的客户分配不同的名称。
另请参见维基百科上的 Abstract factory pattern。
示例:
var customers = new List<CustomerBase> {
new GoldCustomer("Frank"),
new SilverCustomer("Jack")
};
foreach (CustomerBase c in customers) {
Console.WriteLine($"{c.Name} is {c.Type}");
}
打印:
Frank is Gold
Jack is Silver