-1

Basic従業員の給与は、との 2 つの要素から計算されStandardPointます。1 人の従業員は、毎月 1 つの Basic ポイントと 1 つ以上の (またはまったくない) StandardPoint を取得します。

StarPerformerPoint 、 RecognitionPoint 、 ReferralPoint 、 BrandingPoint など、さまざまな StandardPoints があります。

TotalAnnualSalary を計算する機能があります。従業員は、1 年間に最大 4 つの標準ポイントを利用する資格があります。これ以上点を取っても年俸合計は4点しか出ません。

次のコードがあります。それは正常に動作します。ただし、非効率的なメモリ使用率があります。StandardPointElement は複数回作成されます。

このシナリオでオブジェクトの作成を最適化するにはどうすればよいでしょうか?

アップデート

Flyweight パターンのようなものを使用できますか?

ウィキペディアはFlyweight パターンについて述べています

flyweight は、他の同様のオブジェクトとできるだけ多くのデータを共有することによって、メモリの使用を最小限に抑えるオブジェクトです。これは、単純な反復表現が容認できない量のメモリを使用する場合に、多数のオブジェクトを使用する方法です。

Flyweight Design Pattern - C#の記事で、Shailendra Chauhan は次のように述べています。

外部データは実行時にオンザフライで計算され、flyweight オブジェクトの外部に保持されます。したがって、ステートフルにすることができます。

Flyweight パターンが実用的なのはなぜですか?

コード

interface ISalaryScoreElement
{
    int SalaryScore { get; }
}

public class BasicElement : ISalaryScoreElement
{
    public int SalaryScore
    {
        get
        {
            return 100;
        }
    }

}

public class StandardPointElement : ISalaryScoreElement
{
    public int SalaryScore
    {
        get
        {
            return 10;
        }
    }

}

従業員クラス

class Employee
{
    private List<string> eligibility;
    public List<string> EligibleSalaryTypes
    {
        get
        {
            return eligibility;
        }
    }

    public Employee(List<string> eligibility)
    {
        this.eligibility = eligibility;
    }

    public int GetTotalAnnualSalary()
    {
        int totalSalary = 0;
        ISalaryScoreElement sal = null;
        CalculatorFactory factory = new CalculatorFactory();

        int occurenceCountForStandardPoint = 0;

        foreach (string salaryType in EligibleSalaryTypes)
        {
            switch (salaryType)
            {
                case "Basic":
                    sal = factory.GetSalaryElement("BasicElement");
                    break;

                case "ReferralPoint":
                    sal = factory.GetSalaryElement("StandardPointElement");
                    break;

                case "BrandingPoint":
                    sal = factory.GetSalaryElement("StandardPointElement");
                    break;

                case "RecognitionPoint":
                    sal = factory.GetSalaryElement("StandardPointElement");
                    break;

                case "StarPerformerPoint":
                    sal = factory.GetSalaryElement("StandardPointElement");
                    break;

                default:
                    throw new Exception("No mapping available");
            }

            if (sal is StandardPointElement)
            {
                occurenceCountForStandardPoint++;
                if (occurenceCountForStandardPoint > 4)
                {
                    //StandardPointElement can be considered a maximum of 4 times for salary calculation
                    continue;
                }
            }


            totalSalary = totalSalary + sal.SalaryScore;

        }

        return totalSalary;
    }



}

工場

class CalculatorFactory
{
    public ISalaryScoreElement GetSalaryElement(string salaryKey)
    {
        ISalaryScoreElement c = null;
        switch (salaryKey)
        {
            case "BasicElement":
                c = new BasicElement();
                break;
            case "StandardPointElement":
                c = new StandardPointElement();
                break;
            default:
                throw new Exception("Factory cannot create the object specified");
        }
        return c;
    }
}

クライアント

class Program
{
    static void Main(string[] args)
    {
        List<string> eligibleBonus = new List<string>();

        //For January 2013
        eligibleBonus.Add("Basic");
        eligibleBonus.Add("StarPerformerPoint");

        //For February 2013
        eligibleBonus.Add("Basic");
        eligibleBonus.Add("StarPerformerPoint");
        eligibleBonus.Add("ReferralPoint");

        //For March 2013
        eligibleBonus.Add("Basic");
        eligibleBonus.Add("BrandingPoint");
        eligibleBonus.Add("RecognitionPoint");

        //For April 2013
        eligibleBonus.Add("Basic");
        eligibleBonus.Add("BrandingPoint");


        Employee e = new Employee(eligibleBonus);
        int effectiveSalary =  e.GetTotalAnnualSalary();


        Console.WriteLine(effectiveSalary);
        Console.ReadKey();
    }

}
4

4 に答える 4

1

あなたは実際にメモリを使い果たしていますか、それとも何か?

とにかく、一度だけ作成したいクラスのSingleton パターンをいつでも実装できます。実装方法に関する最良の議論は、Jon Skeet によるものです: http://csharpindepth.com/Articles/General/Singleton.aspx

于 2014-02-06T14:45:28.130 に答える
1

にシングルトンパターンを使用したいようですStandardPointElement。これを行うには、単一の値を保持する静的フィールドを作成します。消費者は、 を述べる代わりにこの値を使用しますnew StandardElementPoint()。またprotected、消費者が誤って新しい値を作成するのを防ぐためにコンストラクターを作成しました

public class StandardPointElement : ISalaryScoreElement
{
    public static readonly StandardPointElement Instance = 
       new StandardPointElement();

    protected StandardPointElement() { } 

    public int SalaryScore
    {
        get
        {
            return 10;
        }
    }
}

new StandardElementPoint新しいコード内のすべての使用をに変換しますStandardElementPoint.Instance

于 2014-02-06T14:55:26.627 に答える
0

フライウェイトパターンを使用しています。[しかし、これは最善の解決策ではないかもしれません]

ここに画像の説明を入力

参考文献

  1. C# でのシングルトン パターンの実装 - Jon Skeetは、スレッド セーフについても話します。
  2. Flyweight パターンが実用的なのはなぜですか?
  3. Flyweight デザイン パターン - C#

フライウェイトファクトリー

class CalculatorFlyweightFactory
{
    Dictionary<string, ISalaryScoreElement> calculators = new Dictionary<string, ISalaryScoreElement>();

    public int TotalObjectsCreated
    {
        get { return calculators.Count; }
    }

    public ISalaryScoreElement GetSalaryElement(string salaryKey)
    {
        ISalaryScoreElement c = null;
        if (calculators.ContainsKey(salaryKey))
        {
            c = calculators[salaryKey];
        }
        else
        {
            switch (salaryKey)
            {
                case "BasicElement":
                    c = new BasicElement();
                    calculators.Add("BasicElement", c);
                    break;
                case "StandardPointElement":
                    c = new StandardPointElement();
                    calculators.Add("StandardPointElement", c);
                    break;
                default:
                    throw new Exception("Factory cannot create the object specified");
            }
        }
        return c;
    }
}

フライウェイト

interface ISalaryScoreElement
{
    int SalaryScore { get; }

    //Newly Added
    int OccurenceCount { get; set; }
}

public class BasicElement : ISalaryScoreElement
{
    public int SalaryScore
    {
        get
        {
            return 100;
        }
    }

    public int OccurenceCount { get; set; }
}

public class StandardPointElement : ISalaryScoreElement
{
    public int SalaryScore
    {
        get
        {
            return 10;
        }
    }

    public int OccurenceCount { get; set; }
}

関数

    public int GetTotalAnnualSalary()
    {
        int totalSalary = 0;

        ISalaryScoreElement sal = null;
        CalculatorFlyweightFactory flyweightFactory = new CalculatorFlyweightFactory();

        foreach (string salaryType in EligibleSalaryTypes)
        {
            switch (salaryType)
            {
                case "Basic":
                    sal = flyweightFactory.GetSalaryElement("BasicElement");
                    break;

                case "ReferralPoint":
                    sal = flyweightFactory.GetSalaryElement("StandardPointElement");
                    break;

                case "BrandingPoint":
                    sal = flyweightFactory.GetSalaryElement("StandardPointElement");
                    break;

                case "RecognitionPoint":
                    sal = flyweightFactory.GetSalaryElement("StandardPointElement");
                    break;

                case "StarPerformerPoint":
                    sal = flyweightFactory.GetSalaryElement("StandardPointElement");
                    break;

                default:
                    throw new Exception("No mapping available");
            }

            if (sal is StandardPointElement && sal.OccurenceCount >= 4)
            {
                //StandardPointElement can be considered a maximum of 2 times for salary calculation
                continue;
            }

            sal.OccurenceCount = sal.OccurenceCount + 1;
            totalSalary = totalSalary + sal.SalaryScore;

        }

        return totalSalary;
    }
于 2014-02-07T10:51:34.237 に答える