我喜欢 Mujahid Daud Khan 对使用 C# 8.0 模式的回答。对于多态的方式,我认为这篇文章是 TLDR :P
在基本层面上,我们可以这样做:
using System;
using System.Collections.Generic;
namespace ConsoleApp4
{
class Program
{
static void Main()
{
var builder = new IconSelectorBuilder();
Console.WriteLine($"{nameof(Device.DevIsIOS)}, false");
foreach (var item in builder.Build(Device.DevIsIOS, false).GetIcons())
{
Console.WriteLine(item);
}
Console.WriteLine($"{nameof(Device.DevIsIOS)}, true");
foreach (var item in builder.Build(Device.DevIsIOS, true).GetIcons())
{
Console.WriteLine(item);
}
//Console.WriteLine($"{nameof(Device.Other)}, false");
//foreach (var item in builder.Build(Device.Other, false).GetIcons())
//{
// Console.WriteLine(item);
//}
//Console.WriteLine($"{nameof(Device.Other)}, true");
//foreach (var item in builder.Build(Device.Other, true).GetIcons())
//{
// Console.WriteLine(item);
//}
}
}
public enum Device
{
DevIsIOS,
Other
}
public class IconSelectorBuilder
{
public IIconSelector Build(Device device, bool showIcons)
{
return device switch
{
Device.DevIsIOS => new DevIsIOSIconSelector(showIcons),
_ => new OtherIconSelector(showIcons),
};
}
}
public interface IIconSelector
{
public bool ShowIcons { get; set; }
IEnumerable<Icon> GetIcons();
}
public abstract class IconSelectorBase : IIconSelector
{
public bool ShowIcons { get; set; }
protected IconSelectorBase(bool showIcons)
{
ShowIcons = showIcons;
}
protected abstract IEnumerable<Icon> GetHideIcons();
protected abstract IEnumerable<Icon> GetShowIcons();
public IEnumerable<Icon> GetIcons() => ShowIcons ? GetShowIcons() : GetHideIcons();
}
public sealed class DevIsIOSIconSelector : IconSelectorBase
{
public DevIsIOSIconSelector(bool showIcons) : base(showIcons)
{
}
protected override IEnumerable<Icon> GetHideIcons()
{
yield return new Icon
{
IconType = IconType.GT,
MyProperty1 = 0,
MyProperty2 = 0,
};
yield return new Icon
{
IconType = IconType.FR2,
MyProperty1 = 1,
MyProperty2 = 0,
};
}
protected override IEnumerable<Icon> GetShowIcons()
{
yield return new Icon
{
IconType = IconType.FR1,
MyProperty1 = 0,
MyProperty2 = 0,
};
yield return new Icon
{
IconType = IconType.GT,
MyProperty1 = 1,
MyProperty2 = 0,
};
yield return new Icon
{
IconType = IconType.FR2,
MyProperty1 = 2,
MyProperty2 = 0,
};
}
}
public sealed class OtherIconSelector : IconSelectorBase
{
public OtherIconSelector(bool showIcons) : base(showIcons)
{
}
protected override IEnumerable<Icon> GetHideIcons()
{
// TODO
throw new NotImplementedException();
}
protected override IEnumerable<Icon> GetShowIcons()
{
// TODO
throw new NotImplementedException();
}
}
public class Icon
{
public IconType IconType { get; set; }
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public override string ToString() => $"{IconType}, {MyProperty1}, {MyProperty2}";
}
public enum IconType
{
FR1,
GT,
FR2,
CE
}
}
这个想法是创建IconSelectorBuilder 并提供App.devIsIOS/whatever、App.ShowIcons/whatever 之类的参数(我假设为布尔值)。然后我们构造一个继承自IconSelectorBase 的适当类,该类为布尔参数(App.ShowIcons/'whatever')提供逻辑。然后适当的类将返回适当的图标。
输出:
DevIsIOS, false
GT, 0, 0
FR2, 1, 0
DevIsIOS, true
FR1, 0, 0
GT, 1, 0
FR2, 2, 0