答案:即使将类转换为变量然后调用它们也可行,在这种情况下,它可能是设计糟糕的迹象。更好的设计会产生副作用,不需要不断开始新的类实例。
============
最近我(试图)将SRP应用到我的代码中,将所有职责分成不同的类。它工作得非常好,代码的可维护性和可重用性也增加了很多..但我发现自己经常做new Table.Type("messages").Get(id);
之类的事情。
我的大多数类只包含一个方法。仍然......感觉很尴尬。 Guts说这是我可能将它们全部变成静态类的重点。
所以我想我会转向我更有经验的老年人,经常写'新的Class()。方法()'常见吗?或者有更好的方法来处理它吗?
示例代码:
public void AdminCommands(Channel channel, IrcUser user, string message)
{
var command = message.Split(' ')[0];
switch (command)
{
case "@info":
GetInfo(channel, message);
break;
//----a couple of more commands
}
}
private void GetInfo(Channel channel, string message)
{
Match match = Regex.Match(message, "@info (.+)");
if (match.Success)
{
string search = match.Groups[1].Value;
//Get stored data on the word or sentence, and send the result to chat.
new CommandInfo().Execute(search); //<-------------------- over here.
return;
}
Chat.SendAdminMessage("Message not found.");
}
private void EditMessage(Channel channel, string message)
{
Match match = Regex.Match(message, "@edit (.+?) (.+?) (.+?)=(.+)");
if (match.Success)
{
string type = match.Groups[1].Value;
string id = match.Groups[2].Value;
string toReplace = match.Groups[3].Value;
string replaceWith = match.Groups[4].Value;
//Gets message of 'type' by 'id', and store it back after editing.
new CommandEdit().Execute(type, id, toReplace, replaceWith); //<-here.
}
}
答案 0 :(得分:3)
您当然可以将CommandEdit和CommandInfo存储为成员变量,然后调用Execute
private CommandInfo mInfo = new CommandInfo();
private void GetInfo(Channel channel, string message)
{
Match match = Regex.Match(message, "@info (.+)");
if (match.Success)
{
string search = match.Groups[1].Value;
//Get stored data on the word or sentence, and send the result to chat.
mInfo.Execute(search); //<-------------------- over here again.
return;
}
Chat.SendAdminMessage("Message not found.");
}
答案 1 :(得分:2)
从您的示例代码中很难说,但您似乎正在创建具有面向对象的假装外套的过程代码。
我无法从对象模型中了解您的代码。例如,这条线到底是做什么的?
new CommandInfo().Execute(search);
什么是CommandInfo对象?它代表什么? Execute()函数到底是做什么的?我不知道。
对象的全部意义在于它们封装了某种内部状态。如果你经常新事物,那么他们显然没有任何状态。
您的许多代码似乎都在对消息进行操作,那么为什么不在消息类上放置对消息进行操作的方法呢?
Message.GetInfo();
Message.Edit();
等。当我无法弄清楚它所做的代码时,很难建议一个模型,但是你能看到这使代码变得更加明显吗?
答案 2 :(得分:1)
我建议你检查你的对象模型,并验证导致1-1类方法的设计。如果你仍然认为你的建模是可以接受的,我不推荐静态类方法,特别是如果你进行单元测试,这可能会使你的自动化测试最终具有挑战性。
而不是静态,考虑实现一个基本的单元:
public class Work
{
private static readonly Lazy<Work> _work = new Lazy<Work>(()=> new Work());
public static Work Instance{get{return _work.Value;}}
public void DoWork(){}
}
打电话给它:
Work.Instance.DoWork();
答案 3 :(得分:1)
为什么不为您的类创建一个字段,该字段包含对您不断创建的对象的引用? 像这样你可以避免垃圾收集而你没有创建无用的对象,请参阅:
public class myClass{
...
private ICommandInfo commandInfo= new CommandInfo();
private void GetInfo(Channel channel, string message)
{
Match match = Regex.Match(message, "@info (.+)");
if (match.Success)
{
string search = match.Groups[1].Value;
//Get stored data on the word or sentence, and send the result to chat.
commandInfo.Execute(search); //<-------------------- no object creation.
return;
}
Chat.SendAdminMessage("Message not found.");
}
...
}
我倾向于使用界面ICommandInfo
进一步使用,这将使测试和模拟变得更容易。
答案 4 :(得分:1)
提供某种功能的类也可以被认为是一般意义上的服务。在消费类中注入这些服务是一个好主意(Dependency injection,Inversion of control)。
public class Consumer
{
private ICommandService _commandInfo;
public Consumer(ICommandService commandInfo)
{
_commandInfo = commandInfo;
}
public void DoSomething()
{
_commandInfo.Execute();
}
}
此类服务可以在应用程序启动时创建一次。或者实施Singleton pattern。
使用注入允许您使用不同的实现,而消费类无需了解它。您甚至可以在制作unit tests时注入虚拟课程(请参阅Mock object)。
在您的示例中,不清楚应用Execute
的内容,因为CommandInfo
似乎不包含任何数据。您的评论说“......并将结果发送到聊天室”。为什么不使用注入该类的聊天对象?
_chat.Send(search);
这比new CommandInfo().Execute(search);
说得更多,而且评论已经过时了。解释代码的注释通常暗示代码有问题。提供背景信息的评论是可以的。