You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中借助设计模式简化重复代码的技术实现问询

解决代码重复:用委托或策略模式实现通用逻辑

嘿,针对你现在的代码重复问题,其实咱们可以用委托或者策略模式来搞定,其中委托的方式更轻量直接,先给你看具体实现:

首先,整理你的现有代码(方便对照)

抽象类与子类

public abstract class Base 
{ 
    public int ID { get; set; } 
    public string Countries {get;set;} 
} 

public class ClassA : Base 
{ 
    public string City { get;set; } 
} 

public class ClassB : Base 
{ 
    public string Village{ get;set; } 
} 

public class ComponentClass 
{ 
    public List<ClassA> classAObj { get; set; } 
    public List<ClassB> classBObj { get; set; } 
}

// 业务对象类
public class Parent { public List<Star> Curves { get; set; } = new List<Star>(); }
public class Star { public string Area { get; set; } public string Color { get; set; } public List<TinyStar> Values { get; set; } = new List<TinyStar>(); }
public class TinyStar { public string smallD { get; set; } }

原重复逻辑(已修正小问题)

Main() 
{ 
    ComponentClass[] c = /* Data from 3rd party */; 
    foreach(var data in c) 
    { 
        Parent p = new Parent(); 
        if(data.classAObj.Count > 0) 
        { 
            Star s = new Star(); 
            s.Area = "infinite"; 
            s.Color = "red"; 
            List<string> sep = data.classAObj.SelectMany(a => a.City.Split(',')).ToList(); 
            foreach(var b in sep) 
            { 
                TinyStar t = new TinyStar(); 
                t.smallD = b; 
                s.Values.Add(t); 
            } 
            p.Curves.Add(s); 
        } 
        if(data.classBObj.Count > 0) 
        { 
            Star s2 = new Star(); 
            s2.Area = "infinite"; 
            s2.Color = "red"; 
            List<string> sep = data.classBObj.SelectMany(b => b.Village.Split(',')).ToList(); 
            foreach(var b in sep) 
            { 
                TinyStar t = new TinyStar(); 
                t.smallD = b; 
                s2.Values.Add(t); 
            } 
            p.Curves.Add(s2); 
        } 
    } 
}

注:原代码里有个小错误,data.City应该是遍历classAObj里的每个对象取City属性,我这里先修正了,不然会编译报错~


方案1:用委托实现通用方法(最简洁)

我们可以把“获取分隔字符串”的逻辑作为委托参数传给通用方法,这样通用方法只需要专注于重复的逻辑,不用关心具体取哪个属性:

定义通用方法

// 通用方法:处理单个Base对象集合,以及对应的属性获取逻辑
public void ProcessItems<T>(List<T> items, Parent parent, Func<T, string> getSeparatorString) 
    where T : Base
{
    if(items?.Count > 0)
    {
        Star star = new Star
        {
            Area = "infinite",
            Color = "red"
        };

        // 提取所有分隔后的字符串
        var allParts = items.SelectMany(item => getSeparatorString(item).Split(','));

        foreach(var part in allParts)
        {
            star.Values.Add(new TinyStar { smallD = part });
        }

        parent.Curves.Add(star);
    }
}

在Main里调用通用方法

Main() 
{ 
    ComponentClass[] c = /* Data from 3rd party */; 
    foreach(var data in c) 
    { 
        Parent p = new Parent(); 
        // 处理ClassA集合,传入获取City的委托
        ProcessItems(data.classAObj, p, a => a.City);
        // 处理ClassB集合,传入获取Village的委托
        ProcessItems(data.classBObj, p, b => b.Village);
    } 
}

这样一来,原来两段重复的逻辑就完全合并了,后续如果有新的子类(比如ClassC,有Town属性),只需要加一行ProcessItems(data.classCObj, p, c => c.Town)就行,非常灵活。


方案2:用策略模式(更适合复杂场景)

如果后续的逻辑会变得更复杂,比如除了获取属性还有其他差异操作,那策略模式会更合适:

定义策略接口

public interface IItemProcessor
{
    void Process(List<Base> items, Parent parent);
}

// ClassA对应的策略实现
public class ClassAProcessor : IItemProcessor
{
    public void Process(List<Base> items, Parent parent)
    {
        var classAItems = items.Cast<ClassA>().ToList();
        if(classAItems.Count == 0) return;

        Star star = new Star { Area = "infinite", Color = "red" };
        var allCities = classAItems.SelectMany(a => a.City.Split(','));
        foreach(var city in allCities)
        {
            star.Values.Add(new TinyStar { smallD = city });
        }
        parent.Curves.Add(star);
    }
}

// ClassB对应的策略实现
public class ClassBProcessor : IItemProcessor
{
    public void Process(List<Base> items, Parent parent)
    {
        var classBItems = items.Cast<ClassB>().ToList();
        if(classBItems.Count == 0) return;

        Star star = new Star { Area = "infinite", Color = "red" };
        var allVillages = classBItems.SelectMany(b => b.Village.Split(','));
        foreach(var village in allVillages)
        {
            star.Values.Add(new TinyStar { smallD = village });
        }
        parent.Curves.Add(star);
    }
}

定义通用处理方法

public void CommonMethod(List<Base> items, Parent parent, IItemProcessor processor)
{
    processor.Process(items, parent);
}

在Main里调用

Main() 
{ 
    ComponentClass[] c = /* Data from 3rd party */; 
    foreach(var data in c) 
    { 
        Parent p = new Parent(); 
        // 处理ClassA
        CommonMethod(data.classAObj.Cast<Base>().ToList(), p, new ClassAProcessor());
        // 处理ClassB
        CommonMethod(data.classBObj.Cast<Base>().ToList(), p, new ClassBProcessor());
    } 
}

这种方式的好处是,每个子类的处理逻辑都封装在单独的策略类里,后续修改或扩展时不会影响其他逻辑,适合业务逻辑比较复杂的场景。


总结

  • 如果只是简单的属性差异,委托方案更简洁高效,代码量更少;
  • 如果后续有更多差异化的业务逻辑,策略模式更符合开闭原则,扩展性更好。

内容的提问来源于stack exchange,提问作者user1400915

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:24:37