BlogEngine学习(1)Provider模式

引入

     首先什么是Provider模式?Provider是由两个设计模式融合而来的:策略模式+抽象工厂模式。这两个模式具体的介绍我在这里就不多说了,网上一搜一大把。provider模式的作用是为一个API进行定义和实现的分离。这样就通过核心功能的灵活性和易于修改的特点使得API具有灵活性。通俗一点来说就是实现了定义和实现的分离,最终效果就是不需要更改代码即可实现程序不同逻辑的改变。

     在BlogEngine中,provider模式被应用于提供不同的数据的持久化。为了保证解压后就能使用默认采用的是xmlProvider。本文研究的重点就是了解这个Provider模式,并知道BlogEngine如何通过provider模式使得不同数据持久化方式之间的灵活切换。

实现Provider

     先来看看我实现的Provider模式例子的关系图:

2010-12-06_205354

上图中的各个类已经表明了作用。下面我还会在讲解代码的过程中具体解释这些类的。需要说明的是Provider模式不仅仅是可以为系统提供不同的数据持久方式,在业务逻辑中也同样可以提供不同的方式,不一定要拘泥于数据库这块。

     先来编写BlogProvider和BlogProviderCollection 。这个类是个抽象类,定义了需要实现的抽象方法以便于子类实现。为了演示的方便,这里我就写了一个方法:

namespace ProviderTest
{
    public abstract class BlogProvider:ProviderBase
    {
        public abstract string GetPage();
    }

    public class BlogProviderCollection : ProviderCollection
    {
        public new BlogProvider this[string name]
        {
            get { return (BlogProvider)base[name]; }
        }

        public override void Add(ProviderBase provider)
        {
            if (provider == null)
                throw new ArgumentNullException("provider");

            if (!(provider is BlogProvider))
                throw new ArgumentException
                    ("Invalid provider type", "provider");

            base.Add(provider);
        }
    }
}

从上面可以看到BlogProvider类继承了ProviderBase类。这个类是.net为我们提供的,里面定义了provider操作的一些“规范”。BlogProviderCollection类用于管理Provider集合,它继承于ProviderCollection类,这个类也是系统提供的,简化了provider操作的步骤。在BlogService中我们会用到这个类来初始化provider集合信息。

      下面我再编写DbBlogProvider和XmlBlogProvider类。这两个类继承了BlogProvider类。这是策略模式里面将不同的操作封装起来,使得具体方法的变化不会影响到使用方法的客户。

    public class DbBlogProvider :BlogProvider
    {
        public override string GetPage()
        {
            return "GetPage by db";
        }

        //重写BlogBase里面的Initialize方法
        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "blogProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            base.Initialize(name, config);
        }
    }



    public class XmlBlogProvider:BlogProvider
    {
        public override string GetPage()
        {
            return "GetPage by XML";
        }

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (string.IsNullOrEmpty(name))
                name = "blogProvider";

            if (null == config)
                throw new ArgumentException("config参数不能为null");

            base.Initialize(name, config);
        }
    }

接着再看BlogProviderConfigureSection这个类,这个类可以看成一个管理配置文件中节点的类。后面在BlogService中获得配置文件的信息就靠它了。在这个类中的属性上面采用了Attribute的方式声明值,具体里面的值可以通过反射得到。

    public class BlogProviderConfigureSection:ConfigurationSection
    {
        [ConfigurationProperty("providers")]
        public ProviderSettingsCollection Providers
        {
            get { return (ProviderSettingsCollection)base["providers"]; }
        }

        [StringValidator(MinLength = 1)]
        [ConfigurationProperty("defaultProvider", DefaultValue = "XmlBlogProvider")]
        public string DefaultProvider
        {
            get { return (string)base["defaultProvider"]; }
            set { base["defaultProvider"] = value; }
        }
    }

最后就是我们BlogService类了。在BlogEngine中这个类是业务层和表现层的纽带,表现层通过这个方法调用业务层。也可以这样说,这个类实现了业务层的一个统一的访问接口,这样使得代码层次就比较清晰了,可以理解为装饰模式。代码如下:

        private BlogProvider _provider;
        private BlogProviderCollection _providerCollection;

        public BlogService()
        {
            LoadProvider();
        }

        private void LoadProvider()
        {
            BlogProviderConfigureSection config = null;

            if (_provider==null)
            {
                //获得blogProvider节点信息
                config = (BlogProviderConfigureSection)ConfigurationManager.GetSection("blogProvider");

                _providerCollection = new BlogProviderCollection();
                //下面这个方法是系统提供的,位于System.web下。如果编写的是form程序则需要自己实现这个providhelper
                //有兴趣的 可以查看一下他的源码
                ProvidersHelper.InstantiateProviders(config.Providers, _providerCollection, typeof(BlogProvider));
                //上面那个方法已经加载了providerCollection,这里我们只要DefaultProvider的provider即可
                _provider = _providerCollection[config.DefaultProvider];
            }
        }

        public string GetPage()
        {
           return _provider.GetPage();
        }

最后不要忘了配置一下web.config,不然程序可不知道用哪个方法。在configsections里面添加:

<section name="blogProvider" type="ProviderTest.BlogProviderConfigureSection,ProviderTest" />


然后在configuration下增加:

  <blogProvider defaultProvider="XmlBlogProvider">
    <providers>
      <add name="XmlBlogProvider" type="ProviderTest.XmlBlogProvider"/>
      <add name="DbBlogProvider" type="ProviderTest.DbBlogProvider"/>
    </providers>
  </blogProvider>


最后写一个页面简单的调用一下就可以看到结果了。当你设置改变defaultProvider这个属性值的时候,浏览器简单刷新一下就已经得到了你更改后的结果。

BlogEngine中的Provider

    BlogEngine中实现provider的方式基本上和上面讲的差不多。有点区别的地方在于BlogEngine的XmlProvider中,采用了partial关键字定义了XmlProvider类,这样就实现了不同功能的分离,结构更加清晰。

 2010-12-07_132621

Demo下载

     Demo下载

原文地址:https://www.cnblogs.com/qianlifeng/p/1899343.html