Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#每个用户的策略模式_C#_Design Patterns_Strategy Pattern_Code Structure - Fatal编程技术网

c#每个用户的策略模式

c#每个用户的策略模式,c#,design-patterns,strategy-pattern,code-structure,C#,Design Patterns,Strategy Pattern,Code Structure,我有一个非常简单的场景。 我的网站的用户可以是月度会员或年度会员 public class User { public string UserName { get; set; } public MembershipType MembershipType { get; set; } } public enum MembershipType { MONTHLY, ANNUALLY } 然后根据会员资格,我采用不同的计费策略: public interface IB

我有一个非常简单的场景。 我的网站的用户可以是月度会员或年度会员

public class User
{
    public string UserName { get; set; }
    public MembershipType MembershipType { get; set; }
}

public enum MembershipType
{
    MONTHLY,
    ANNUALLY
}
然后根据会员资格,我采用不同的计费策略:

public interface IBillingStrategy
{
    void Bill(User user);
}

if (user.MembershipType == MembershipType.ANNUALLY)
{
     _billingStrategy = new AnnualBillingStrategy();
}
else if (user.MembershipType == MembershipType.MONTHLY)
{
      _billingStrategy = new MonthlyBillingStrategy();
}
这是非常直接和简单的。现在生意来了,说:“我想照顾我的朋友鲍勃,我想让你计算他的账单时和其他人略有不同!”

因此,如果我继续这种模式,我可以制定一个跳跃策略。然后我可以添加一些额外的逻辑,现在我有两种方法可以识别Bob

if (user.UserName.Equals("bob"))
{
     _billingStrategy = new BobBillingStrategy();
}
这让我感觉很肮脏,因为我正在硬编码一个用户名,而我的运气就是bob创建了一个新用户。所以我可以向我的用户IsBob添加一个布尔属性

if (user.IsBob)
{
     _billingStrategy = new BobBillingStrategy();
}
我觉得这两样东西都很好闻。我可以看到将会发生什么,最终我将开始测试弗雷德,还有泰德。我上面的代码可以工作,但我确信一定有更干净的解决方案


谢谢

对计费程序进行另一种更改:

public enum MembershipType
{
    MONTHLY,
    ANNUALLY,
    SPECIAL1
}

这样,您至少可以将相同的过程分配给其他一些“朋友”

我将成为持有默认账单的类的成员,等等。如果有一堆if,这将是一件非常干净的事情:

public class Membership
{

    public String Name { get; private set; }
    public BillingStrategy DefaultBillingStrategy {get; private set; }
    //Other properties

        public Membership(string name, BillingStrategy defaultBillingStrategy)
        {

            Name = name;
            DefaultBillingStrategy = defaultBillingStrategy;

        }

}
然后,对用户执行以下操作:

public class User
{

    //same as before

    public BillingStrategy BillingStrategy {get; set; }

    public User(string Name, Membership membership, BillingStrategy billingStrategy = null)
    {

        name = Name;
        MemberShip = memberShip;
        BillingStrategy = billingStrategy ? membership.DefaultBillingStrategy;

    }

}
enter code here

还有,;由于如果用户在7月加入,则不想为jan thorugh jun付费,因此您可能希望在用户身上保存一些关于会员资格何时到期的信息,并让会员在计费时/计费后设置此值添加某种优惠券代码机制,因此,如果您需要为其他用户进行不同的计算,那么它足够灵活,可以执行相同的操作

你的IBillingStrategy到底是做什么的

它是否负责实际向用户计费以及计算用户应支付的费用

如果是这样,我会将这些责任分开,引入
发票
的概念,然后允许在实际向
用户
计费之前,将特定于用户的
折扣
应用到生成的
发票

我可能会结合
会员
账单策略
(因此
会员
生成
发票
),使用
账单操作
来封装用户的账单方式(信用卡、邮寄发票、未标记账单公文包)引入
折扣的概念
(每个
用户
可以有许多
折扣
)来处理新的需求,并将整个过程打包成一个
计费服务

当从您拥有的任何商店为用户补水时,我会给他们一个适当的
会员资格
(这反过来会用一组
折扣
和其他信息初始化,如会员日期等)和一个适当的
账单操作


然后,作为计费过程的一部分(可能是每晚的事情),你得到
用户
,将他们推到
计费服务
,然后在下面生成
发票
,并使用
用户
计费操作

是的,就像这里回答的人一样,你只需要实现这些“好友策略”在代码中,但策略必须用于的确切用户应在数据库级别上进行配置。至少,这似乎是对我来说最不肮脏的解决方案。不建议使用枚举来存储成员资格类型。使成员资格成为动态的东西(请参阅我的答案)顺便说一句,有没有可能从另一个角度来看待这个问题?例如,不是为Bob添加新的
IBillingStrategy
,而是添加新的业务对象,比如说,
折扣
,可以为其他用户重复使用?这只是一个想法,我不知道你的确切问题。我对这个解决方案的问题是这么多年了在这条线上,未来的编码器将有更多的WTF/分钟时刻,因为“special1”是什么还不是很清楚。此外,它仍然失去了用户每月或每年一次的事实(这可能会影响其他地方的代码逻辑)只是一个输入错误:
用户
不再是
//与以前一样
,因为你必须持有
账单策略
。在我看来,你似乎不必要地把
会员资格方面的事情复杂化了,因为“//与以前一样”我指的是它的其他属性(名称和会员资格)。我不明白你怎么能说我不必要地使成员身份复杂化。我更愿意说,将不同类型的成员身份硬编码为一个枚举,然后使用一堆硬编码的if来检查该枚举,以更改一些与成员身份持续时间一样微不足道的内容,这会使事情更加复杂。对不起,我没有注意到
BillingStrategy
属性,我完全不好。你将
BillingStrategy
注入
成员身份
,这意味着其他类必须控制该进程,或者你甚至需要一个新类来控制该进程。
BillingStrategy
现在被注入到两个类中,需要更多的机制来支持它。我认为这是不必要的我很复杂。没问题。如果我看起来很暴躁,我很抱歉。太多咖啡+睡眠不足+饥饿=暴躁的程序员:PI编辑了我的评论。是的,硬编码很多ifs肯定比让
成为一个类成员更糟糕,我非常同意你。