C# - 代码重构

2021-02-09 12:15

阅读:328

隐藏更多

只暴露集合中供人使用的单一功能,将关于集合的更多功能隐藏掉。

旧版本

public class Animal
{
    private Liststring> LanguageList = new Liststring>
    {
        "#$%^",
        "@*",
        "中文",
        "英文"
    };

    public IListstring> GetLanguageList( )
    {
        return LanguageList;
    }
}

public class Programe
{
    static void Main( string[] args )
    {
        Animal a = new Animal( );
        var language = a.GetLanguageList( );
        language[0]=
    }
}

IList具有索引器,可以通过数组检索的方式设置元素的值,而我们只想让用户调用枚举器对集合进行简单的迭代或查询,但并不需要他们插手对集合元素的值的更改。所以此时就要考虑让GetLanguageList方法返回一个IEnumerable,由于IEnumerable只有一个GetEnumerator的方法,它没有索引器,所以它只能提供一个枚举器供用户调用,从而防止了集合元素被修改的可能。

技术分享图片技术分享图片

新版本

public IEnumerablestring> GetLanguageList( 
{
    return LanguageList; //方法返回的LanguageList隐式转换为了IEnumerablestring>

}

提升成员

将完全重名的字段、属性、方法提升到基类,供每个子类调用。

聚合模拟多继承

为了使没有逻辑上的继承关系的两个类强行发生关系,可以将其中一个类作为另一个类的成员来存取。

抽象解耦

如果其它类需要与某个类(x)发生关系,则可以将x类抽象成一个接口,将其成员抽象到接口中,其它类只需要和接口发生关系,而不需要直接与x发生关系,好处在于如果今后删除了x,我们还可以创建y类来实现接口,这样就不会影响与接口发生关系的那些类。接口就像角色那样,x具有这个角色所要求的的功能,所以x=此角色,y具有这个角色所要求的的功能,那么y也=此角色,对于其它想要与x发生 关系的那些类来说,它们完全可以只需要与角色发生关系,而不用在乎这个角色是由谁来扮演,所以如果x后来死掉了,它们是不用感到惊慌失措的,因为它们只关心和其发生关系的角色。

用属性替代字段

关键思路:多使用属性,少用字段。因为字段过于粗略,而属性由于多了两个方法块,就可以提供更精细的操作逻辑,在设置或获取数据之前你就可以编码出更多的细节控制。

常量封装

如果一些频繁使用的常量总是存在于方法的代码块中,假如有100个方法都在使用这些常量,而今后需求变更,需要更改这个常量值,你就需要把存在于100个方法中的这个常量值给修改掉,工作量巨大而且毫无乐趣,简单的办法就是,将这种普遍存在于各个方法中的常量封装成一个方法的返回值抑或封装到枚举中以应对将来可能发生的需求变更,需求变更时,只需要在封装的方法里或枚举中修改这个常量值即可。

方法分割

如果一个方法中的逻辑代码过于臃肿,就很难让人去尝试阅读,也不方便调试,更不利于需求变更时的代码修改,方法应该作为一个单一的功能供其它方法调用,所以,将一个有N个操作逻辑的方法分割成多个方法,每个方法只提供一个单一的功能,这样就更便于阅读、理解和修改。

封装条件

如果一个条件判断中有多个条件,这会使代码难以阅读,将条件的逻辑判断封装成望文即可生义的属性或方法后,只需要使用属性或方法做判断即可。如果条件需要用某个参数做判断则把判断的逻辑定义成方法,否则定义成属性即可。

旧版

public class Test
{
    public void Show( string arg )
    {
        if (arg.Trim( new char[] { ‘u‘, ‘p‘ } ).Length > 10 && arg.Contains( "s" ) && arg.LastIndexOf( "a" ) != -1) { }
        if (DateTime.Now.Hour == 12 && DateTime.Now.DayOfWeek == DayOfWeek.Monday && DateTime.Now.DayOfYear == 1984) { }
    }
}

新版

public class Test
{
    public bool IsArgPass( string arg ) { return arg.Trim( new char[] { ‘u‘, ‘p‘ } ).Length > 10 && arg.Contains( "s" ) && arg.LastIndexOf( "a" ) != -1; }
    public bool IsNowTimePass { get { return DateTime.Now.Hour == 12 && DateTime.Now.DayOfWeek == DayOfWeek.Monday && DateTime.Now.DayOfYear == 1984; } }
    public void Show( string arg )
    {
        //望文生义,IsArgPass表示参数是否通过测试
        if (IsArgPass( arg )) { }
        //望文生义,IsDatimePass表示当前时间是否正确
        if (IsNowTimePass) { }
    }
}

移除条件

如果一个类需要根据条件调用不同的方法,假如有100个条件就需要判断100次。这样就降低了代码的复用性和灵活性。为此,可以使用一个简单的策略,将条件作为哈希字典的key,将对应的方法作为哈希字典的Value,当用户传递一个条件到类中,类只需要从哈希字典去取出Key所对应方法即可。

旧版本

//国籍
public enum Country { UnitedKingdom = 1  1, Japan = 1  2, China = 1  3 }

//语言
public class Language
{
    public void UnitedKingdomLanguage() { Console.WriteLine( "hello" ); }
    public void JapanLanguage( ) { Console.WriteLine( "ハロー" ); }
    public void ChinaLanguage( ) { Console.WriteLine( "你好" ); }
}

//服务
public class Service
{
    private Language Language = new Language( );
    //根据国籍提供不同版本的语言对话
    public void ShowLanguage( Country country )
    {
        switch (country)
        {
            case Country.Japan:
                Language.JapanLanguage( );
                break;
            case Country.China:
                Language.ChinaLanguage( );
                break;
            case Country.UnitedKingdom:
                Language.UnitedKingdomLanguage( );
                break;
        }
    }
}
Service service = new Service( );
service.ShowLanguage( Country.Japan );

新版本

//国籍
public enum Country { UnitedKingdom = 1  1, Japan = 1  2, China = 1  3 }

//语言接口
public interface ILanguage
{
    void UnitedKingdomLanguage( );
    void JapanLanguage( );
    void ChinaLanguage( );
}

//语言
public class Language:ILanguage
{
    public void UnitedKingdomLanguage() { Console.WriteLine( "hello" ); }
    public void JapanLanguage( ) { Console.WriteLine( "ハロー" ); }
    public void ChinaLanguage( ) { Console.WriteLine( "你好" ); }
}

//服务
public class Service
{
    private ILanguage Language;
    private DictionaryCountry,Action> LanguageMethodDictionary { get; set; }
    public Service( ILanguage language )
    {
        this.Language = language;
        LanguageMethodDictionary = new DictionaryCountry, Action>
        {
            { Country.China, Language.ChinaLanguage },
            { Country.Japan, Language.JapanLanguage },
            { Country.UnitedKingdom, Language.UnitedKingdomLanguage },
        };
    }
     
    //根据国籍提供不同版本的语言对话
    public void ShowLanguage( Country country )
    {
        LanguageMethodDictionary[country]( );
    }
}
Service service = new Service( new Language() );
service.ShowLanguage( Country.Japan );

尽早返回

如果一个方法中有大量的条件分支语句,这会使得整个逻辑走向变得不清晰,最佳做法是尽早return,把不满足条件的情况尽早返回,这样可以使代码更容易理解和阅读。

  

 

  

C# - 学习总目录


评论


亲,登录后才可以留言!