-1

员工的工资由两个要素计算得出 -BasicStandardPoint。一名员工每月将获得一个基本积分和一个或多个(或没有)标准积分。

有各种 StandardPoints,即 StarPerformerPoint、RecognitionPoint、ReferralPoint、BrandingPoint。

有计算 TotalAnnualSalary 的功能。一年内,一名员工最多可获得 4 个标准积分。即使他得到更多的分数,也只会计算 4 来计算年薪总额。

我有以下代码。它工作正常。但是,内存利用率不高。StandardPointElement 被创建多次。

在这种情况下,我们如何优化对象创建?

更新

我们可以使用享元模式之类的东西吗?

维基百科说关于享元模式

享元是一种通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象;当简单的重复表示将使用不可接受的内存量时,这是一种使用大量对象的方法。

在文章Flyweight Design Pattern - C#中,Shailendra Chauhan 提到了以下内容

外部数据是在运行时动态计算的,它保存在享元对象之外。因此它可以是有状态的。

为什么享元模式实用?

代码

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

你真的是内存不足还是什么?

无论如何,您总是可以为您只希望创建一次的类实现单例模式。关于如何实施的最佳讨论是 Jon Skeet:http ://csharpindepth.com/Articles/General/Singleton.aspx

于 2014-02-06T14:45:28.130 回答
1

factory.GetSalaryElement("BasicElement");在循环开始之前,只调用factory.GetSalaryElement("StandardPointElement");一次,然后重用循环中的对象。

或者,如果您真的无事可做,则将一个内部字典Dictionary<string, ISalaryScoreElement>作为CalculatorFactory类的字段,如果当前对象不存在,则将填充该字段,如果对象确实存在,则从其中检索该对象。

于 2014-02-06T14:43:04.063 回答
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. 为什么享元模式实用?
  3. 享元设计模式 - 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 回答