• 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下载

  • 相关阅读:
    mysql索引
    mysql锁机制
    mysql授权
    mysql执行计划
    mysql知识补遗
    求助:springboot调用存储过程并使用了pagehelper分页时报错com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException
    java面试题1
    Yarn
    MapRudecer
    Hive数据倾斜和解决办法
  • 原文地址:https://www.cnblogs.com/qianlifeng/p/1899343.html
Copyright © 2020-2023  润新知