gpt4 book ai didi

c# - 工厂模式和对象持久性

转载 作者:行者123 更新时间:2023-11-30 23:14:08 25 4
gpt4 key购买 nike

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

4年前关闭。




Improve this question




我在我的应用程序的一个部分中使用工厂设计模式,我注意到使用常规工厂模式每次都会创建一个新对象。我有一个场景,我需要多次迭代工厂类中的 createinstance 方法,并且每次创建新的消费者对象时。

在 Program.cs 中,我创建了人员列表,我在其中键入了一些随机输入数据。基于对每个人的操作的代码应该动态地执行该类中的 process 方法。这个逻辑似乎像我预期的那样工作,但是如果重复相同的操作,那么会多次创建相同的对象。

为了解决这个问题,我修改了 ActionFactory 类(如下面的 Modified Action Factory 片段所示),我在其中维护一个字典来保存为特定操作创建的实例。如果重复该操作,则不是创建新实例,而是从字典中获取先前创建的实例。这似乎已经解决了问题,如 Output2 图像所示。

但是我想知道/向专业人士学习,如果我在“Modified Action Factory”类中所做的工作是否足够(或者)对于这类问题我应该使用其他模式而不是工厂设计模式。为了维护单个对象,我能想到的另一种方法可能是在每个 Action 类中创建一个单例对象,但问题是如何从工厂类调用单例实例?因为工厂类总是调用 createinstance 而不会调用单例实例..我是设计模式的新手,我正在努力学习更多关于它们的知识并提高我的编码标准。提前致谢

下面是代码:

  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; }

}

Action 工厂:
public class ActionFactory
{
Dictionary<string, Type> actions;

public ActionFactory()
{
LoadTypesICanReturn();
}

public object CreateInstance(string actionName)
{
Type t = GetTypeToCreate(actionName);

if (t == null)
return null;

var actionProcessor = Activator.CreateInstance(t) as IAction;

return 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);
}
}
}
}

Action :
   public interface IAction
{
void Process();
}

添加.cs
  public class Add: IAction
{

public Add()
{
Console.WriteLine("add constructor...");
}

#region IAction Members

public void Process()
{
Console.WriteLine("Add Processor....");
}

#endregion
}

更新.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 消费者类被实例化的次数

输出:

enter image description here

修改后的 Action 工厂:
 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);
}
}
}
}

带有修改的 Action 工厂的输出:

enter image description here

最佳答案

Factory设计模式用于简化对象的创建,通常当您不知道要创建的类型时,它将在运行时提供。
有时,也可能是因为它们有依赖关系,而你想抽象依赖关系的创建,或者只是因为你想做一些事情。

在您的情况下,Add , Update , 和 Delete是通常由某些第 3 方调用的方法,而不是数据类型本身,由 @sokohavi 指定多于。

您的案件可以由Command Design Pattern 处理.

假设你想加载一堆命令(又名:Add Person X, Update Person Y, Delete Person 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());

现在,这是您可以做什么的基本示例。
也许,在某些情况下, Command s 不是那么容易创建的,例如,它们可能需要了解 REST 请求的服务端点。

为此,一个 CommandFactory可以创建,然后可以通过操作名称处理创建:
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());

任何事物都有设计模式,您应该只找到适合您需要的设计模式。

关于c# - 工厂模式和对象持久性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43310187/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com