簡體   English   中英

如何使用OOP設計模式更好地實現基類屬性可擴展性機制

[英]How to better implement base class property extencibility mechanism with OOP design patterns

在我的項目中,我具有實現自定義屬性的類層次結構。 這里更接近我想要的控制台應用程序版本。

class Property
{
    string key;
    object value;

    public Property(string key, object value)
    {
        this.key = key;
        this.value = value;
    }

    public override string ToString()
    {
        return "(key=" + key + ": value=" + value + ")";
    }
}

public struct PropertyConfig
{
    public string key;
    public object defaultValue;
}

abstract class BaseClass
{
    Dictionary<string, Property> properties = new Dictionary<string, Property>();

    Dictionary<string, PropertyConfig> mergedConfigs = new Dictionary<string, PropertyConfig>();

    public BaseClass()
    {
        MergeWithInheritedConfigsAndCreateInstances(
            new PropertyConfig[]
            {
                new PropertyConfig() { key = "p1",  defaultValue = "v1" },
                new PropertyConfig() { key = "p2",  defaultValue = "v2" }
            }, 
            true);
    }

    protected void MergeWithInheritedConfigsAndCreateInstances(PropertyConfig[] configs = null, bool IsBaseClass = false)
    {
        configs = configs ?? new PropertyConfig[] { };

        foreach (PropertyConfig config in configs)
        {
            mergedConfigs[config.key] = config;
        }

        if (!IsBaseClass)
        {
            CreatePropertyInstancesAfterMerge();
        }
    }

    private void CreatePropertyInstancesAfterMerge()
    {
        foreach (KeyValuePair<string, PropertyConfig> kvp in mergedConfigs)
        {
            PropertyConfig config = kvp.Value;

            properties.Add(config.key, new Property(config.key, config.defaultValue));
        }
    }

    public override string ToString()
    {
        return GetType().Name + ".Properties: " + string.Join(",", properties.Select(kvp => kvp.Value.ToString()).ToArray());
    }
}

class DerivedClassA : BaseClass
{
    public DerivedClassA(): base()
    {
        MergeWithInheritedConfigsAndCreateInstances();
    }
}

class DerivedClassB : BaseClass
{
    public DerivedClassB() : base()
    {
        MergeWithInheritedConfigsAndCreateInstances(new PropertyConfig[]
        {
            new PropertyConfig() { key = "p2",  defaultValue = true },
            new PropertyConfig() { key = "p3",  defaultValue = "v3" }
        });
    }
}

class DerivedClassC : BaseClass
{
    public DerivedClassC() : base()
    {
        MergeWithInheritedConfigsAndCreateInstances(new PropertyConfig[]
        {
            new PropertyConfig() { key = "p2",  defaultValue = false },
            new PropertyConfig() { key = "p4",  defaultValue = "v4" }
        });
    }
}

class Program
{
    static void Main(string[] args)
    {
        DerivedClassA derivedA = new DerivedClassA();
        DerivedClassB derivedB = new DerivedClassB();
        DerivedClassC derivedC = new DerivedClassC();

        Console.WriteLine(derivedA.ToString());
        Console.WriteLine(derivedB.ToString());
        Console.WriteLine(derivedC.ToString());


        Console.ReadLine();
    }
}

基本抽象類定義其屬性對象的配置,這些屬性旨在在派生類中繼承。

在構造函數中,將數組傳遞給MergeWithInheritedConfigsAndCreateInstances方法調用,並將第二個參數設置為true指示必須延遲屬性對象的實例化。

合並屬性配置的當前狀態存儲在mergedConfigs Dictionary

派生類將本地屬性配置傳遞給合並/覆蓋,而基類配置將在其構造函數中調用MergeWithInheritedConfigsAndCreateInstances方法,並將第二個參數設置為其默認值false指示現在必須在合並后創建屬性實例。

結果輸出如下。

DerivedClassA.Properties: (key=p1: value=v1),(key=p2: value=v2)
DerivedClassB.Properties: (key=p1: value=v1),(key=p2: value=True),(key=p3: value=v3)
DerivedClassC.Properties: (key=p1: value=v1),(key=p2: value=False),(key=p4: value=v4)

這就是我所需要的,但是我不喜歡這種解決方案的一些缺點:

1)必須在每個構造函數中調用MergeWithInheritedConfigsAndCreateInstances 必須在抽象類構造函數中提供第二個參數。

我想要一個在基類中實現並調用所有合並/實例化機制的解決方案。 為了能夠將派生類特定的屬性配置定義為不是方法參數,而是成員字段/屬性(也許是靜態的)。

2)每次實例化類時,都會完成合並過程。

我希望只完成一次。 (放置在靜態構造函數中?)

UPD:重新編寫的示例代碼可以更好地演示預期的想法。

我認為您太過復雜了。 即使對於復雜的設置,這也足夠了:

class BaseClass
{
    private readonly Dictionary<string, string> properties = new Dictionary<string, string>();
    protected string this[string key]
    {
        get { string value; return properties.TryGetValue(key, out value) ? value : null; }
        set { if (value == null) properties.Remove(key); else properties[key] = value; }
    }

    public BaseClass()
    {
        this["p1"] = "v1";
        this["p2"] = "v2";
    }

    public override string ToString()
    {
        return GetType().Name + ".Properties: " + string.Join(",", properties.Select(kvp => $"{kvp.Key}:{kvp.Value}"));
    }
}

class DerivedClass : BaseClass
{
    public DerivedClass() : base()
    {
        this["p2"] = "update";
        this["p3"] = "v3";
    }
}

但坦率地說,這更加簡單和明顯:

class BaseClass
{
    public string P1 {get;set;}
    public string P2 { get; set; }
    public BaseClass()
    {
        P1 = "v1";
        P2 = "v2";
    }
    public override string ToString()
    {
        return GetType().Name + ".Properties: " + string.Join(",", GetType().GetProperties(
            BindingFlags.Public | BindingFlags.Instance).Select(p => $"{p.Name}:{p.GetValue(this)}"));
    }
}

class DerivedClass : BaseClass
{
    public string P3 { get; set; }
    public DerivedClass() : base()
    {
        P2 = "update";
        P3 = "v3";
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM