• 继承和复用


    目录

    背景设计的演化待重构的代码用继承消除重复用扩展类(Mixin)消除重复Ruby的鸭子类型 + Mixin的实现备注

    背景返回目录

    今天上午和以为朋友聊了一个设计问题:如何消除仓库相关的单据的Repository中的重复逻辑?如:入库单Repository和出库单Repository之间的重复。可以有很多方式消除重复,在不同级别消除重复,如:继承、组合、掺入、帮助类、帮助方法。本文只说出我的观点:不要为了复用而使用继承

    设计的演化返回目录

    下面我会演示:待重构的重复代码-》用继承消除重复-》用扩展类(Mixin)消除重复-》Ruby的鸭子类型 + Mixin的实现(元编程可以更牛叉,有机会再说)。

    待重构的代码返回目录

    注意:出库单仓储和入库单仓储的“根据编号获取单据”重复了。

    类图

    代码

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Linq.Expressions;
     7 
     8 namespace CSharpStudy.MixinStudy.V1
     9 {
    10     class Aggregate { }
    11 
    12     interface IRepository<T> where T : Aggregate
    13     {
    14         IEnumerable<T> Where(Expression<Func<T, bool>> condition);
    15     }
    16 
    17     class Repository<T> : IRepository<T>
    18         where T : Aggregate
    19     {
    20         public IEnumerable<T> Where(Expression<Func<T, bool>> condition)
    21         {
    22             throw new NotImplementedException();
    23         }
    24     }
    25 
    26     class 入库单 : Aggregate
    27     {
    28         public string 单据编号 { get; set; }
    29     }
    30 
    31     class 出库单 : Aggregate
    32     {
    复制代码

    用继承消除重复返回目录

    当我看到上面的重复代码的时候,第一印象是引入两个基类:仓库单据基类和仓库单据仓储基类。

    类图

    代码

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Linq.Expressions;
     7 
     8 namespace CSharpStudy.MixinStudy.V2
     9 {
    10     class Aggregate { }
    11 
    12     interface IRepository<T> where T : Aggregate
    13     {
    14         IEnumerable<T> Where(Expression<Func<T, bool>> condition);
    15     }
    16 
    17     class Repository<T> : IRepository<T>
    18         where T : Aggregate
    19     {
    20         public IEnumerable<T> Where(Expression<Func<T, bool>> condition)
    21         {
    22             throw new NotImplementedException();
    23         }
    24     }
    25 
    26     class 仓库单据基类 : Aggregate
    27     {
    28         public string 单据编号 { get; set; }
    29     }
    30 
    31     class 入库单 : 仓库单据基类 { }
    32 
    33     class 出库单 : 仓库单据基类 { }
    34 
    35     class 仓库单据仓储基类<T> : Repository<T>
    36         where T : 仓库单据基类
    37     {
    38         public IEnumerable<T> 根据编号获取单据(string 单据编号)
    39         {
    40             return this.Where(x => x.单据编号 == 单据编号);
    41         }
    42     }
    43 
    44     class 入库单仓储 : 仓库单据仓储基类<入库单> { }
    45 
    46     class 出库单仓储 : 仓库单据仓储基类<出库单> { }
    47 }
    复制代码

    用扩展类(Mixin)消除重复返回目录

    我对了吗?没有多态,只是为了复用就引入继承,是否合理呢?

    类图

    代码

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 using System.Linq.Expressions;
     7 
     8 namespace CSharpStudy.MixinStudy.V3
     9 {
    10     class Aggregate { }
    11 
    12     interface IRepository<T> where T : Aggregate
    13     {
    14         IEnumerable<T> Where(Expression<Func<T, bool>> condition);
    15     }
    16 
    17     class Repository<T> : IRepository<T>
    18         where T : Aggregate
    19     {
    20         public IEnumerable<T> Where(Expression<Func<T, bool>> condition)
    21         {
    22             throw new NotImplementedException();
    23         }
    24     }
    25 
    26     class 仓库单据基类 : Aggregate
    27     {
    28         public string 单据编号 { get; set; }
    29     }
    30 
    31     class 入库单 : 仓库单据基类 { }
    32 
    33     class 出库单 : 仓库单据基类 { }
    34 
    35     static class 仓库单据基类仓储扩展
    36     {
    37         public static IEnumerable<T> 根据编号获取单据<T>(this IRepository<T> that, string 单据编号)
    38             where T : 仓库单据基类
    39         {
    40             return that.Where(x => x.单据编号 == 单据编号);
    41         }
    42     }
    43 }
    复制代码

    Ruby的鸭子类型 + Mixin的实现返回目录

    代码

    复制代码
     1 # coding: utf-8
     2 
     3 class Aggregate
     4 end
     5 
     6 class Repository
     7     def Where(condition)
     8     end
     9 end
    10 
    11 class C仓库单据基类 < Repository
    12     attr_accessor :单据编号
    13 end
    14 
    15 class C入库单 < C仓库单据基类
    16 end
    17 
    18 class C出库单 < C仓库单据基类
    19 end
    20 
    21 module C仓库单据基类仓储扩展
    22     def 根据编号获取单据(单据编号)
    23         return self.Where({:单据编号 => 单据编号})
    24     end
    25 end
    26 
    27 class C入库单仓储 < Repository
    28     include C仓库单据基类仓储扩展
    29 end
    30 
    31 class C出库单仓储 < Repository
    32     include C仓库单据基类仓储扩展
    33 end
    复制代码

    Ruby正统的支持了Mixin,鸭子类型天生具备泛型的特点,比泛型强大,元编程更是牛叉(本文没有体现)。

    备注返回目录

     做一件事如果只有一个选择,就说明 有问题了,多思考几个方案,折中后考虑一个方案。

  • 相关阅读:
    pytorch 多gpu训练
    pytorch简单测试
    预处理
    机器学习:模型评估与选择:性能度量——代价敏感错误率与代价曲线
    机器学习:模型评估与选择:性能度量——ROC与AUC
    机器学习:模型评估与选择:性能度量——查准率、查全率与F1
    机器学习:模型评估与选择:评估方法——交叉验证法(筹)
    机器学习:模型评估与选择:评估方法——自助法
    机器学习:模型评估与选择:评估方法——留出法
    机器学习:绪论
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3277783.html
Copyright © 2020-2023  润新知