如何用C#实践Policy based design

简介

http://www.codeproject.com/KB/cs/PolicyBasedCS.aspx

这篇是我在CodeProject的发文,在这篇文章中我用一个简单的范例示范如何在C#实践Policy based design的手法。

Policy的意思是方针,或策略,也就是将原本复杂的系统,拆解成多个独立运作的“策略类型”(policy class),每一组policy class都只负责单纯如行为(behavior, method)或结构(structure)的某一方面。

除此之外我们还需要一个宿主类(host class),只需要切换不同 Policy Class,就可以得到不同的需求。

我个人认为在policy based design中,最重要的并不是所谓的design,而是分析(Analysis)。

重点不在于怎么样设计出policy,而是怎么将需求分析拆解成policy based的设计。

我们可以把这种设计思路,用生活上的例子来解释。

举例来说:做菜

料理= 食材+调味+烹调

食材包括了:牛,羊,猪,鸡,青菜,等等各种食物

调味包括了:酸,甜,苦,辣,等各种调味方式,以及调味料。

烹调包括了:煎,煮,烤,炸等等各种手法。

我们可以把所有的食材当成一个方针(policy)的群组;调味也当成一个方针(policy)的群组;烹调也是。

而料理,则是一个宿主类型(host class)。

透过食材,调味以及烹调的组合,就可以产出不同的料理。

黑胡椒牛排=牛肉+黑胡椒+煎(或烤)

烤全鸡=鸡+烤肉酱+烤

范例说明

在这个范例中,我将档名的控制分成三个Policy群组。

第一个群组是CBIFileNamePolicy,这是提供档名主体的方针。

第二个群组是CBIFilenameExtensionPolicy,这是用来处理延伸档名的方针。

第三个群组是CBFileNameControlPolicy,这是用来控制主档名的方针。

在我的设计中,我也提供了三组宿主类(host class)

    /// <summary>
    /// This policy will get name from CBIFileNamePolicy
    /// </summary>
    /// <typeparam name="TNamePolicy">Must be CBIFileNamePolicy</typeparam>
    public sealed class CBFileName<TNamePolicy> : CBFileName
        where TNamePolicy : CBIFileNamePolicy,new()
    {
        TNamePolicy _policy;
        public CBFileName()
            : base()
        {
            _policy = new TNamePolicy();
        }
        public override string Name
        {
            get
            {
                return _policy.Name;
            }
            set
            {
                _policy.Name = value;
            }
        }
    }

第一个宿主类非常简单,只是单纯的取得CBIFileNamePolicy的Name属性而已。

    /// <summary>
    /// This policy will get name from CBIFileNamePolicy.Name + "." + CBIFilenameExtensionPolicy.Name
    /// </summary>
    /// <typeparam name="TNamePolicy">Must be CBIFileNamePolicy</typeparam>
    /// <typeparam name="TNameExtensionPolicy">Must be CBIFilenameExtensionPolicy</typeparam>
    public sealed class CBFileName<TNamePolicy, TNameExtensionPolicy> : CBFileName
        where TNamePolicy : CBIFileNamePolicy, new()
        where TNameExtensionPolicy : CBIFilenameExtensionPolicy, new()
    {
        TNamePolicy _policy1;
        TNameExtensionPolicy _policy2;
        public CBFileName()
            : base()
        {
            _policy1 = new TNamePolicy();
            _policy2 = new TNameExtensionPolicy();
        }
        public override string Name
        {
            get
            {
                return _policy1.Name + "." + _policy2.Name;
            }
            set
            {
                _policy1.Name = value;
            }
        }
    }


第二个宿主类,则是CBIFileNamePolicy.Name + "." + CBIFilenameExtensionPolicy.Name

来取得主档名及延伸档名

    /// <summary>
    /// This policy will get name from
    /// CBIFileNamePolicy.Name + "_" + CBIFileNameControlPolicy.Name + "." + CBIFilenameExtensionPolicy.Name
    /// </summary>
    /// <typeparam name="TNamePolicy">Must be CBIFileNamePolicy</typeparam>
    /// <typeparam name="TNameControlPolicy">Must be CBIFileNameControlPolicy</typeparam>
    /// <typeparam name="TNameExtensionPolicy">Must be CBIFilenameExtensionPolicy</typeparam>
    public sealed class CBFileName<TNamePolicy, TNameControlPolicy, TNameExtensionPolicy> : CBFileName, CBIFileNameControlPolicy
        where TNamePolicy : CBIFileNamePolicy, new()
        where TNameControlPolicy : CBIFileNameControlPolicy, new()
        where TNameExtensionPolicy : CBIFilenameExtensionPolicy, new()
    {
        TNamePolicy _policy1;
        TNameControlPolicy _policy2;
        TNameExtensionPolicy _policy3;

        public CBFileName()
            : base()
        {
            _policy1 = new TNamePolicy();
            _policy2 = new TNameControlPolicy();
            _policy3 = new TNameExtensionPolicy();
        }

        string FileName
        {
            get
            {
                return _policy1.Name + "_" + _policy2.Name + "." + _policy3.Name;
            }
        }

        public override string Name
        {
            get
            {
                Control();
                return FileName;
            }
            set
            {
                _policy1.Name = value;
            }
        }

        public void Control()
        {
            while (true)
            {
                FileInfo info = new FileInfo(FileName);
                if (info.Exists && info.Length > MaxSplitSize)
                {
                    _policy2.Control();
                }
                else
                {
                    break;
                }
            }
        }
    }

第三个宿主类则是取得CBIFileNamePolicy.Name + "_" + CBIFileNameControlPolicy.Name + "." + CBIFilenameExtensionPolicy.Name
的档名格式。


客户端使用范例

CBFileName name1 =
    new CBFileName<CBFileNamePolicy, CBTextExtensionPolicy>();
name1.Name = "Test1";
Console.WriteLine(name1.Name);

这个范例会得到Test1.txt。

若是将CBTextExtensionPolicy换成CBXmlExtensionPolicy,则会得到Test1.xml。


范例UML




范例代码下载

欢迎到我的资源下载代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值