Rom*_*ier 60 c# design-patterns command-pattern
我的问题与命令模式有关,我们有以下抽象(C#代码):
public interface ICommand
{
void Execute();
}
Run Code Online (Sandbox Code Playgroud)
让我们来看一个简单的具体命令,它旨在从我们的应用程序中删除一个实体.Person
例如,一个实例.
我会有一个DeletePersonCommand
实现的ICommand
.此命令需要Person
删除作为参数,以便在Execute
调用方法时将其删除.
管理参数化命令的最佳方法是什么?在执行参数之前如何将参数传递给命令?
Bla*_*rad 61
您需要通过构造函数或setter注入(或等效项)将参数与命令对象相关联.也许是这样的:
public class DeletePersonCommand: ICommand
{
private Person personToDelete;
public DeletePersonCommand(Person personToDelete)
{
this.personToDelete = personToDelete;
}
public void Execute()
{
doSomethingWith(personToDelete);
}
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*eld 21
通过构造函数或setter传递数据,但需要命令的创建者知道命令所需的数据...
"上下文"的想法非常好,我正在研究(一个内部的)框架,利用它一段时间.
如果设置控制器(与用户交互的UI组件,CLI解释用户命令,解释传入参数和会话数据的servlet等)以提供对可用数据的命名访问,命令可以直接询问他们想要的数据.
我真的很喜欢分离这样的设置允许.考虑分层如下:
User Interface (GUI controls, CLI, etc)
|
[syncs with/gets data]
V
Controller / Presentation Model
| ^
[executes] |
V |
Commands --------> [gets data by name]
|
[updates]
V
Domain Model
Run Code Online (Sandbox Code Playgroud)
如果您"正确"执行此操作,则相同的命令和表示模型可以与任何类型的用户界面一起使用.
更进一步,上面的"控制器"非常通用.UI控件只需要知道名称它们将调用的命令 - 它们(或控制器)不需要知道如何创建该命令或命令需要什么数据.这是真正的优势.
例如,您可以保存要在Map中执行的命令的名称.每当组件被"触发"(通常是actionPerformed)时,控制器会查找命令名称,实例化它,调用execute,并将其推送到撤消堆栈(如果使用的话).
Jua*_*nma 10
有一些选择:
您可以通过属性或构造函数传递参数.
其他选择可能是:
interface ICommand<T>
{
void Execute(T args);
}
Run Code Online (Sandbox Code Playgroud)
并将所有命令参数封装在值对象中.
在创建命令对象时传递此人:
ICommand command = new DeletePersonCommand(person);
Run Code Online (Sandbox Code Playgroud)
这样当你执行命令时,它已经知道它需要知道的一切.
class DeletePersonCommand : ICommand
{
private Person person;
public DeletePersonCommand(Person person)
{
this.person = person;
}
public void Execute()
{
RealDelete(person);
}
}
Run Code Online (Sandbox Code Playgroud)
我的实现是这样的(使用Juanma提出的ICommand):
public class DeletePersonCommand: ICommand<Person>
{
public DeletePersonCommand(IPersonService personService)
{
this.personService = personService;
}
public void Execute(Person person)
{
this.personService.DeletePerson(person);
}
}
Run Code Online (Sandbox Code Playgroud)
IPersonService可以是一个IPersonRepository,它取决于你的命令是什么"层".
小智 5
在这种情况下,我们对Command对象所做的就是创建一个Context对象,该对象本质上是一个地图。该映射包含名称/值对,其中键是常量,而值是Command实现使用的参数。如果您拥有一个命令链,其中以后的命令依赖于先前命令的上下文更改,则特别有用。
所以实际的方法变成
void execute(Context ctx);
Run Code Online (Sandbox Code Playgroud)
已经提到的 Blair Conrad 的代码(不知道如何标记他)如果你知道实例化类时要删除哪个人并且他的方法就足够了,那么效果就很好。但是,如果你不知道你要删除谁删除,直到按下按钮为止,您可以使用返回人员的方法引用来实例化该命令。
class DeletePersonCommand implements ICommand
{
private Supplier<Person> personSupplier;
public DeletePersonCommand(Supplier<Person> personSupplier)
{
this.personSupplier = personSupplier;
}
public void Execute()
{
personSupplier.get().delete();
}
}
Run Code Online (Sandbox Code Playgroud)
这样,当执行命令时,供应商会获取您要删除的人员,并在执行时执行此操作。直到那时,该命令还没有关于要删除谁的信息。
供应商的有用链接。
注意:用java编写的代码。具有 C# 知识的人可以对其进行调整。
归档时间: |
|
查看次数: |
42997 次 |
最近记录: |