• 设计


    设计开篇

     

    1 设计模式

       类是我们面向对象编程的承载工具,可以说是面向对象的起点。
       设计模式,这种算面向对象的进化。按照gof设计模式的分类
       设计模式分为:创建型,结构型,行为型。
       其中创建型主要和类的创建有关
       结构性组织扩展类和类之间的关系
       行为型主要扩展的类的访问
       这三个对应到类上
       创建型模式对应的是构造函数
       结构型对应的是类的属性
       行为型对应类的方法
       就想我们以前学数学中很多证明题,都源自最基本的定理,面向对象编程也有类似的地方
       设计模式就是类最基本功能的一个进化


    2.依赖注入    

      相信大家对Ioc(依赖注入)肯定不陌生,Ioc主要遵循设计原则中的依赖倒置原则,  

      但是假设我们不要把这个东西提升到设计的高度,只看它的功能就会发现,   Ioc创建类正好就是控制类的构造函数,和设计模式中创建型模式有关,  

      例如创建型模式中单例模式用ioc生命周期管理可以达到同样的效果,

      这里以Unity为例,Untiy支持child容器。利用child容器,我们可以在运行时提供更多动态创建的内容。

      我们以asp.net mvc为例,我们可以在session初始化的时候根据不同用户注入不同接口的实现。

      例如我们可以在repository中注入一个默认的规约,当不同用户登录   我们可以将用户对数据的访问权限形成一个规约,

      注册到child容器中,然后在controller激活的时候使用当前session的子容器来激活controller。

      在这里使用例子中,Ioc又实现了类似factory,甚至是building模式的功能(这个例子会在后面的文章中给大家展现具体的实现).


    3.抽象的维度  

      多态是代码的下行  

      抽象是代码的下行

      如果B继承自A,C继承自A,那么A称之为B,C这个维度的抽象,B,C称之为A这个维度的变化 A,B,C称之为一个维度的继承关系

      传统的继承解决的是一个维度的变化,如果我们在这个维度上面引入泛型,并且用where限制泛型的行为 或者属性,

      那么就可以用诸如interface<T1,T2,T3>这样,通过组合几个泛型提供多个维度的变化。 此处用泛型扩展的继承有点类似于多继承。


    4.元数据编程(Attribute)

      Attribute在我所使用的元数据编程占有重要位置。

      在asp.net mvc中,ValueProvider,ModuleBinding,Validator,Filter,都使用了元数据编程。

      不谈这个大的我们看一个更小的例子。

      最早在winform中使用DateGrid的时候,我们都是在grid设计器中去设置列的属性,名称,绑定的字段,等等。

      如果我们引入元数据编程,就可以通过在类的属性上加上特性来扩展。

      这样做更便于维护,当你的界面需要修改时,只需要在绑定的类上做修改,修改的地方相对集中,而不用去操作设计器。


    5. 策略工厂

      上面说了很多理论的东西,下面为大家带来点干货。
      首先我们分析一个简单工厂的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public interface ITest
        {
            void DoSomething();
        }
     
     
        public class Test1: ITest
        {
            public void DoSomething()
            {
     
            }
        }
        public class Test2: ITest
        {
            public void DoSomething()
            {
     
            }
        }
     
     
        public class Factory
        {
            public static ITest Create(string type)
            {
                if (type == "1")
                    return new Test1();
                if (type == "2")
                    return new Test2();
                throw new NotImplementedException();
            }
        }

    分析简单工厂的弊端  

      1,扩展不方便需要改动create的逻辑  

      2,客户需要知道create的具体逻辑 

      3,创建类型过于单一导致简单工厂类的泛滥  

      4,无法为对象创建提供灵活性,例如构造函数参数  

      5,无法实现运行时扩展

    下面我对简单工厂做了一些改造

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    public  interface IStrategy
    {
    }
     
    public interface IGenericsFactory<TStrategy>
        where TStrategy : IStrategy
    {
     
        /// <summary>
        /// 注册处理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        void Regist(Type type);
     
     
        /// <summary>
        /// 获取处理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        TStrategy GetStrategy(string name);
     
        /// <summary>
        /// 获取所有的处理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        List<string> GetStrategys();
    }
     
    public class GenericsFactory<TStrategy> : IGenericsFactory<TStrategy>
        where TStrategy : IStrategy
    {
        public GenericsFactory()
        {
            if (_strategys == null)
            {
                _strategys = GetType().Assembly
                        .GetTypes()
                        .Where(item => item.GetInterfaces().Contains(typeof(TStrategy)) || item.IsSubclassOf(typeof(TStrategy)))
                        .Where(item => !item.IsAbstract)
                        .ToDictionary(item =>
                        {
                            var desc = item.GetCustomAttribute<DescriptionAttribute>();
                            return desc != null ? desc.Description : string.Empty;
                        }, item => item);
            }
        }
     
        protected Dictionary<string, Type> _strategys;
     
        public void Regist(Type type)
        {
            if (type.GetInterfaces().Contains(typeof(TStrategy)) && type.IsSubclassOf(typeof(TStrategy)))
                throw  new TypeLoadException(string.Format("类型不是从{0},继承",typeof(TStrategy).Name));
            if (_strategys.ContainsKey(MetaDataManager.Attribute.GetDescription(type)))
                return;
            _strategys.Add(MetaDataManager.Attribute.GetDescription(type), type);
        }
     
        public TStrategy GetStrategy(string name)
        {
            if (!_strategys.ContainsKey(name))
                _strategys.Add(name, typeof(TStrategy));
            return (TStrategy)UnityService.Resolve(_strategys[name]);
        }
     
     
        public List<string> GetStrategys()
        {
            return _strategys.Keys.ToList();
        }
    }

    改造思路
      1,使用将create的类型标记在对应的接口实现上,反射获取子类的特性,如果新增加一个类型只
           需要增加子类,并且在子类添加特性
      2,将所有可用子类的元素据缓存起来,在工厂构造函数中反射所有子类和子类的特性用字典缓存起来
           并且所有可创建的类型暴露给外部
      3,将构造出来的类型做成泛型,并且提供泛型限制,将可构造类型独立出一个维度来变化
      4,通过ioc来动态创建类型
      5,通过提供regist来提供运行时扩展

    使用的案例:
      1,SSO登陆,前台用户和后台用户,存放在不同的数据表,数据结构也可能不一样
      2,动态数据权限配置,例如,某个角色只能访问某部分数据 =,>,<等等这些筛选条件的扩展
      3,状态者模式,状态可扩展,可以由界面去选择某种状态对应那种处理方式,
         将处理方式类型放在数据库
      4,责任链模式中节点的扩展和配置
           通过缓存可以直接所有节点,灵活配置节点来实现流程的功能
      5,装饰器的扩展
      可以搭配装饰器模式配置出先用某个装饰后用某个装饰、


    总结:

      上面的这些关于程序设计的一些思考,会在后面的文章中分享一些自己在实际项目中的
      具体案例,请关注后续文章。要想一个架构设计能顺利推广,最简单粗暴的方法就是这个架构能够帮助程序员少些代码。
      下一篇文章将分享一个,全栈式编程的设计,主要应用于后台系统的增删改查,方便程序员更
      快速的处理掉数据的增删改查这部分通用逻辑

     
     
    标签: 设计
  • 相关阅读:
    git 命令手册
    leetcode #7 revert integer 问题
    leetcode #1 twoSum问题:简单实用哈希表
    c++模板函数分离编译的问题
    matlab 与c/c++ 混合MEX的编程
    springboot项目打war包
    springboot-jpa多数据源
    springboot使用RestTemplate+httpclient连接池发送http消息
    IDEA如何安装lombok
    Springboot如何启用文件上传功能
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5602370.html
Copyright © 2020-2023  润新知