C# 如何避免创建多个对象实例?
员工的工资由两个要素计算—C# 如何避免创建多个对象实例?,c#,oop,design-patterns,flyweight-pattern,C#,Oop,Design Patterns,Flyweight Pattern,员工的工资由两个要素计算—Basic和StandardPoint。一名员工每月将获得一个基本和一个或多个(或无)标准点 有各种标准点,即StarPerformerPoint、RecognitionPoint、ReferralPoint、BrandingPoint 有一个计算TotalAnnualAlary的功能。一年内,员工最多可获得4个标准分数。即使他得到更多的分数,计算总年薪也只会计算4分 我有以下代码。它很好用。但是,内存利用率不高。StandardPointElement被多次创建 在这
Basic
和StandardPoint
。一名员工每月将获得一个基本和一个或多个(或无)标准点
有各种标准点,即StarPerformerPoint、RecognitionPoint、ReferralPoint、BrandingPoint
有一个计算TotalAnnualAlary的功能。一年内,员工最多可获得4个标准分数。即使他得到更多的分数,计算总年薪也只会计算4分
我有以下代码。它很好用。但是,内存利用率不高。StandardPointElement被多次创建
在这种情况下,我们如何优化对象创建
更新
我们可以使用类似flyweight的图案吗
维基百科说
飞锤是一种通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象;当简单的重复表示将使用不可接受的内存量时,这是一种大量使用对象的方法
Shailendra Chauhan在文章中提到以下内容
外部数据在运行时以动态方式计算,并保存在flyweight对象外部。因此它可以是有状态的
代码
员工类别
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 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();
}
}
类程序
{
静态void Main(字符串[]参数)
{
List eligibleBonus=新列表();
//2013年1月
添加(“基本”);
添加(“StarPerformerPoint”);
//2013年2月
添加(“基本”);
添加(“StarPerformerPoint”);
添加(“参考点”);
//2013年3月
添加(“基本”);
添加(“BrandingPoint”);
添加(“认可点”);
//2013年4月
添加(“基本”);
添加(“BrandingPoint”);
员工e=新员工(eligibleBonus);
int effectiveSalary=e.getTotalAnualSalary();
Console.WriteLine(有效工资);
Console.ReadKey();
}
}
调用这两个工厂.GetSalaryElement(“BasicElement”)代码>和工厂.GetSalaryElement(“StandardPointElement”)代码>仅在循环开始之前执行一次,并重用循环中的对象
或者,如果您真的没有更好的事情要做,请使用一个内部字典dictionary
作为CalculatorFactory
类的一个字段,如果当前对象不存在,将填充该字段,如果该对象存在,将从该字段检索该对象。您实际上是内存不足还是其他原因
无论如何,对于只希望创建一次的类,始终可以实现。Jon Skeet对如何实现进行了最好的讨论:听起来您想对StandardPointElement
使用单例模式。为此,创建一个静态字段来保存单个值。消费者将使用此值,而不是声明新的StandardElementPoint()
。我还使构造函数受到保护
,以防止消费者意外地创建新值
public class StandardPointElement : ISalaryScoreElement
{
public static readonly StandardPointElement Instance =
new StandardPointElement();
protected StandardPointElement() { }
public int SalaryScore
{
get
{
return 10;
}
}
}
新建将代码中所有使用的New StandardElementPoint
转换为StandardElementPoint。实例
我正在使用flyweight模式。[但这可能不是最好的解决方案]
参考资料
还讨论了线程安全
飞锤工厂
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;
}
}
作用
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;
}
你已经发布了一堆代码,几乎只是给了我们一些指导,“但是内存利用率不高。StandardPointElement被创建了多次。”。这还不够具体。请更准确地描述你认为你的问题代码在哪里,以及你认为问题到底是什么。@Lijo,在你粘贴的代码中,对象没有内存,所以我仍然不明白你为什么担心这个问题。Flyweight模式在某些情况下很不错,但在这些情况下您没有什么可共享的。。。
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;
}