设计

设计开篇

 

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,装饰器的扩展
  可以搭配装饰器模式配置出先用某个装饰后用某个装饰、


总结:

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

 
 
标签: 设计
原文地址:https://www.cnblogs.com/Leo_wl/p/5602370.html