C# 工厂模式与对象持久性
我在应用程序的一个部分中使用了factory设计模式,我注意到使用常规factory模式每次都会创建一个新对象。我有一个场景,我需要在工厂类中多次迭代createinstance方法,每次创建一个新的使用者对象 在Program.cs中,我创建了人员列表,在其中输入了一些随机输入数据。基于对每个人的操作的代码应该在该类中动态执行process方法。这个逻辑似乎像我预期的那样工作,但是如果重复相同的操作,那么相同的对象会被创建多次 为了解决这个问题,我修改了ActionFactory类(如下面修改的ActionFactory代码片段所示),在该类中我维护了一个字典来保存为特定操作创建的实例。如果重复该操作,那么我将从字典中获取先前创建的实例,而不是创建新实例。这似乎已经解决了Output2图像中所示的问题 但是我想知道/向专业人士学习我在“修改动作工厂”课程中所做的是否足够(或者)对于这类问题,我是否应该使用其他模式来代替工厂设计模式。对于维护单个对象,我可以想到的另一种方法可能是在每个Action类中创建一个Singleton对象,但问题是如何从factory类调用Singleton实例??由于factory类总是调用createinstance,而这不会调用singleton实例。我是设计模式的新手,我很想了解更多关于模式的知识,并提高我的编码标准。提前谢谢 代码如下:C# 工厂模式与对象持久性,c#,factory-pattern,C#,Factory Pattern,我在应用程序的一个部分中使用了factory设计模式,我注意到使用常规factory模式每次都会创建一个新对象。我有一个场景,我需要在工厂类中多次迭代createinstance方法,每次创建一个新的使用者对象 在Program.cs中,我创建了人员列表,在其中输入了一些随机输入数据。基于对每个人的操作的代码应该在该类中动态执行process方法。这个逻辑似乎像我预期的那样工作,但是如果重复相同的操作,那么相同的对象会被创建多次 为了解决这个问题,我修改了ActionFactory类(如下面修改
class Program
{
static void Main(string[] args)
{
List<Person> ListofPeople = new List<Person>();
Person p1 = new Person() {Name = "P1", State = "CA", Action = "Add"};
ListofPeople.Add(p1);
Person p2 = new Person() { Name = "P2", State = "NJ", Action = "Add" };
ListofPeople.Add(p2);
Person p3 = new Person() { Name = "P3", State = "VA", Action = "Update" };
ListofPeople.Add(p3);
Person p4 = new Person() { Name = "P4", State = "VA", Action = "Update" };
ListofPeople.Add(p4);
Person p5 = new Person() { Name = "P5", State = "VA", Action = "Update" };
ListofPeople.Add(p5);
Person p6 = new Person() { Name = "P6", State = "VA", Action = "Delete" };
ListofPeople.Add(p6);
ActionFactory factory= new ActionFactory();
foreach (var person in ListofPeople)
{
IAction action = (IAction) factory.CreateInstance(person.Action.ToLower());
action.Process();
}
Console.ReadKey();
}
}
public class Person
{
public string Name { get; set; }
public string State { get; set; }
public string Action { get; set; }
}
Add.cs
public class Add: IAction
{
public Add()
{
Console.WriteLine("add constructor...");
}
#region IAction Members
public void Process()
{
Console.WriteLine("Add Processor....");
}
#endregion
}
Update.cs
public class Update: IAction
{
public Update()
{
Console.WriteLine("Update constructor...");
}
public void Process()
{
Console.WriteLine("Update Processor...");
}
}
删除.cs
public class Delete : IAction
{
public Delete()
{
Console.WriteLine("Delete Constructor...");
}
#region IAction Members
public void Process()
{
Console.WriteLine("Delete Processor...");
}
#endregion
}
控制台输出显示IAction使用者类实例化的次数
输出:
修改动作工厂:
public class ActionFactory
{
Dictionary<string, Type> actions;
private Dictionary<Type, IAction> actionInstances;
public ActionFactory()
{
actionInstances = new Dictionary<Type, IAction>();
LoadTypesICanReturn();
}
public object CreateInstance(string actionName)
{
Type t = GetTypeToCreate(actionName);
if (t == null)
return null;
if (actionInstances.ContainsKey(t))
return actionInstances[t];
else
{
var actionProcessor = Activator.CreateInstance(t) as IAction;
LoadIAction(t, actionProcessor);
return actionProcessor;
}
}
private void LoadIAction(Type t, IAction actionProcessor)
{
if (!actionInstances.ContainsKey(t))
{
actionInstances.Add(t, actionProcessor);
}
}
Type GetTypeToCreate(string actionName)
{
foreach (var action in actions)
{
if (action.Key.Contains(actionName))
{
return actions[action.Key];
}
}
return null;
}
void LoadTypesICanReturn()
{
actions = new Dictionary<string, Type>();
Type[] typesInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typesInThisAssembly)
{
if (type.GetInterface(typeof(IAction).ToString()) != null)
{
actions.Add(type.Name.ToLower(), type);
}
}
}
}
公共类ActionFactory
{
字典动作;
私有字典实例;
公共行动工厂()
{
actionInstances=新字典();
loadTypesCanReturn();
}
公共对象CreateInstance(字符串actionName)
{
类型t=GetTypeToCreate(actionName);
如果(t==null)
返回null;
if(actionInstances.ContainsKey(t))
返回actionInstances[t];
其他的
{
var actionProcessor=Activator.CreateInstance(t)作为IAction;
LoadIAction(t,actionProcessor);
返回操作处理器;
}
}
专用无效LoadIAction(类型t,IAction actionProcessor)
{
如果(!actionInstances.ContainsKey(t))
{
actionInstances.Add(t,actionProcessor);
}
}
键入GetTypeToCreate(字符串actionName)
{
foreach(行动中的var行动)
{
if(action.Key.Contains(actionName))
{
返回操作[action.Key];
}
}
返回null;
}
void LoadTypesICanReturn()
{
actions=newdictionary();
类型[]typesInThisAssembly=Assembly.GetExecutionGassembly().GetTypes();
foreach(在此程序集中键入Types)
{
if(type.GetInterface(typeof(IAction).ToString())!=null)
{
actions.Add(type.Name.ToLower(),type);
}
}
}
}
具有修改动作工厂的输出:
public class ActionFactory
{
Dictionary<string, Type> actions;
private Dictionary<Type, IAction> actionInstances;
public ActionFactory()
{
actionInstances = new Dictionary<Type, IAction>();
LoadTypesICanReturn();
}
public object CreateInstance(string actionName)
{
Type t = GetTypeToCreate(actionName);
if (t == null)
return null;
if (actionInstances.ContainsKey(t))
return actionInstances[t];
else
{
var actionProcessor = Activator.CreateInstance(t) as IAction;
LoadIAction(t, actionProcessor);
return actionProcessor;
}
}
private void LoadIAction(Type t, IAction actionProcessor)
{
if (!actionInstances.ContainsKey(t))
{
actionInstances.Add(t, actionProcessor);
}
}
Type GetTypeToCreate(string actionName)
{
foreach (var action in actions)
{
if (action.Key.Contains(actionName))
{
return actions[action.Key];
}
}
return null;
}
void LoadTypesICanReturn()
{
actions = new Dictionary<string, Type>();
Type[] typesInThisAssembly = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in typesInThisAssembly)
{
if (type.GetInterface(typeof(IAction).ToString()) != null)
{
actions.Add(type.Name.ToLower(), type);
}
}
}
}
工厂设计模式用于简化对象的创建,通常在您不知道要创建的类型时,并且将在运行时提供。
有时,这也可能是因为它们有依赖项,并且您想要抽象依赖项创建,或者仅仅是因为您想要做一些事情 在您的情况下,
Add
、Update
和Delete
是通常由第三方调用的方法,而不是上面@sokohavi
指定的数据类型本身
您的案例可以通过命令设计模式处理
假设您希望加载一组命令(aka:添加人员X、更新人员Y、删除人员Z
),并希望缓冲这些命令以备将来使用
abstract class PersonCommand
{
Person Person { protected get; } // you can call this payload, or person, w/e
PersonCommand(Person person)
{
Person = person;
}
public abstract void Apply(); // can be called Execute or Process as well, or w/e. problem domain.
}
然后,每个命令都有一个实现:
class AddCommand : PersonCommand
{
AddCommand(Person person) : base(person) { }
public override void Apply()
{
// send REST PUT request, add person to DB, whatever you want to do here.
}
}
class UpdateCommand : PersonCommand
{
UpdateCommand(Person person) : base(person) { }
public override void Apply()
{
// send REST POST request, update person in DB, whatever you want to do here.
}
}
class DeleteCommand : PersonCommand
{
DeleteCommand(Person person) : base(person) { }
public override void Apply()
{
// send REST DELETE request, remove person from DB, whatever you want to do here.
}
}
当您有此功能时,您可以执行以下操作:
var commandsToExecute = new List<PersonCommand>();
commandsToExecute.Add(new AddCommand(new Person { Name = "asd", State = "CA" }));
commandsToExecute.Add(new UpdateCommand(new Person { Name = "barry", State = "CA" }));
commandsToExecute.Add(new DeleteCommand(new Person { Name = "barry", State = "CA" }));
commandsToExecute.ForEach(cmd => cmd.Apply());
其用途是:
var factory = new CommandFactory("http://localhost:4200/person/");
var commandsToExecute = new List<PersonCommand>();
commandsToExecute.Add(factory.Create("add", new Person { Name = "asd", State = "CA" }));
commandsToExecute.Add(factory.Create("update", new Person { Name = "barry", State = "CA" }));
commandsToExecute.Add(factory.Create("delete", new Person { Name = "barry", State = "CA" }));
commandsToExecute.ForEach(cmd => cmd.Apply());
var factory=newcommandfactory(“http://localhost:4200/person/");
var commandsToExecute=new List();
commandsToExecute.Add(factory.Create(“Add”,newperson{Name=“asd”,State=“CA”}));
commandsToExecute.Add(factory.Create(“update”,newperson{Name=“barry”,State=“CA”}));
commandsToExecute.Add(factory.Create(“delete”,newperson{Name=“barry”,State=“CA”}));
commandsToExecute.ForEach(cmd=>cmd.Apply());
任何东西都有设计模式,你应该找到适合你需要的模式。谢谢你,Giora。它为我遇到的问题提供了一个新的解决方案。我会在我的设计中尝试你的解决方案。
class CommandFactory
{
private readonly Dictionary<string, Func<Person, PersonCommand>> creationFuncs;
CommandFactory(string backendUrl)
{
creationFuncs = new Dictionary<string, Func<Command, Person>>();
creationFuncs.Add("add", (person) => return new AddCommand(backendUrl, person));
creationFuncs.Add("update", (person) => return new UpdateCommand(backendUrl, person));
creationFuncs.Add("delete", (person) => return new DeleteCommand(backendUrl, person));
}
PersonCommand Create(string action, Person person)
{
// validation can be added here
return creationFuncs[action](person);
}
}
var factory = new CommandFactory("http://localhost:4200/person/");
var commandsToExecute = new List<PersonCommand>();
commandsToExecute.Add(factory.Create("add", new Person { Name = "asd", State = "CA" }));
commandsToExecute.Add(factory.Create("update", new Person { Name = "barry", State = "CA" }));
commandsToExecute.Add(factory.Create("delete", new Person { Name = "barry", State = "CA" }));
commandsToExecute.ForEach(cmd => cmd.Apply());