假设我有一个Customer
类。客户可以拥有多种忠诚度积分。对于一次促销,客户可能正在收集Rewards
。在另一种情况下,客户可能正在收集Miles
。而且,Customer
并没有固定数量的忠诚度积分。我确信这是一个常见的用例。装饰器模式是否适合以下示例代码?
public interface ICustomer
{
void Display();
}
public class SimpleCustomer : ICustomer
{
public void Display()
{
Console.WriteLine("I am simple customer");
}
}
public abstract class CustomerDecorator : ICustomer
{
protected ICustomer customer;
public CustomerDecorator(ICustomer customer)
{
this.customer = customer ?? throw new ArgumentNullException("customer");
}
public abstract void Display();
}
public class RewardsDecorator : CustomerDecorator
{
private int rewards;
public RewardsDecorator(ICustomer customer, int rewards) : base(customer)
{
this.rewards = rewards;
}
public override void Display()
{
Console.WriteLine("Now I have " + rewards.ToString() + " rewards");
}
}
public class MilesDecorator : CustomerDecorator
{
private int miles;
public MilesDecorator(ICustomer customer, int miles) : base(customer)
{
this.miles = miles;
}
public override void Display()
{
Console.WriteLine("Now I have " + miles.ToString() + " miles");
}
}
答案 0 :(得分:0)
我认为装饰器不是您要寻找的模式。
此外,您的代码似乎不是Decorator模式的实现。您没有在唯一的功能上添加任何功能。您只需覆盖它。但是,添加到现有功能的是Decorator模式的全部意义所在。
我的方法将是状态/策略模式。有不同种类的奖励。客户有一个或多个。这些奖励可以共享一个公共界面并提供不同的实现。客户(或子类或复合对象RewardedCustomer
)应持有这些奖励的列表或地图。
答案 1 :(得分:0)
不要以为装饰器模式可以实现您想要的功能。装饰器在原始类的基础上添加了新功能。一个典型的Wiki示例将说,我们可以在画布顶部添加滚动条,菜单栏,覆盖和其他UI组件。因此,要创建适当的浏览器窗口,您将具有:
public class Canvas
public class ScrollableCanvas
public class OverlayedCanvas
etc.
以便我们为原始Canvas添加更多功能。
要解决您的问题,您应该有类似的东西:
public abstract class LoyaltyProgramAccount {...}
public class RewardAccount extends LoyaltyProgramAccount {...}
public class MilesAccount extends LoyaltyProgramAccount {...}
然后添加一个带有注册感的枚举:
public enum LoyaltyProgramTypes {
miles,
reward,
}
然后让用户成为:
public class Customer {
private List<LoyaltyProgramTypes, LoyaltyProgramAccount> accounts;
public void openAccount(LoyaltyProgramTypes type, LoyaltyProgramAccount account) {
accounts.put(type, account);
}
...
}
答案 2 :(得分:0)
我会使用访客模式,这对于您的情况非常理想。这样,您就可以很好地将针对不同客户类型的奖励计算分开,并针对所有受支持的奖励类型运行操作。
class Program
{
static void Main(string[] args)
{
MilesCustomer customer = new MilesCustomer();
ICustomerVisitor<int> visitor = new MilesCalculation(10);
var miles = customer.Visit(visitor);
visitor = new RewardsCalucation(100);
var rewards = customer.Visit(visitor);
}
}
public interface ICustomerVisitor<T>
{
T Visit(SimpleCustomer cusomter);
T Visit(RewardsCustomer cusomter);
T Visit(MilesCustomer cusomter);
}
public abstract class Customer
{
public Customer()
{
TotalMoneySpent = 10;
}
public int TotalMoneySpent { get; private set; }
public abstract T Visit<T>(ICustomerVisitor<T> visitor);
public virtual void Display()
{
Console.WriteLine("I am simple customer");
}
}
public class RewardsCalucation : ICustomerVisitor<int>
{
private int _rewardsPerDollar;
public RewardsCalucation(int rewardsPerDollar) => _rewardsPerDollar = rewardsPerDollar;
public int Visit(SimpleCustomer cusomter)
{
return 0;
}
public int Visit(RewardsCustomer cusomter)
{
return cusomter.TotalMoneySpent * _rewardsPerDollar;
}
public int Visit(MilesCustomer cusomter)
{
return 0;
}
}
public class MilesCalculation : ICustomerVisitor<int>
{
private int _milesPerDollar;
public MilesCalculation(int milesPerDollar) => _milesPerDollar = milesPerDollar;
public int Visit(SimpleCustomer cusomter)
{
return 0;
}
public int Visit(RewardsCustomer cusomter)
{
return 0;
}
public int Visit(MilesCustomer cusomter)
{
return cusomter.TotalMoneySpent * _milesPerDollar;
}
}
public class SimpleCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}
public class RewardsCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}
public class MilesCustomer : Customer
{
public override T Visit<T>(ICustomerVisitor<T> visitor)
{
return visitor.Visit(this);
}
}