C# 在处理静态方法时保持代码处于同一级别
这可能有点主观,但我想听听你对我目前处境的看法。我有一个类将用于序列化/反序列化对象C# 在处理静态方法时保持代码处于同一级别,c#,java,design-patterns,oop,single-responsibility-principle,C#,Java,Design Patterns,Oop,Single Responsibility Principle,这可能有点主观,但我想听听你对我目前处境的看法。我有一个类将用于序列化/反序列化对象 public class MyClass { public static string ToXmlString( MyClass c ) { /*...*/ } public static MyClass FromXmlString( string xml ) { /*...*/ } } 我之所以喜欢这种方法,是因为它将两个功能保持在同一个级别。但是,我的目标是避免使用静态方法(如果可行)。这
public class MyClass
{
public static string ToXmlString( MyClass c ) { /*...*/ }
public static MyClass FromXmlString( string xml ) { /*...*/ }
}
我之所以喜欢这种方法,是因为它将两个功能保持在同一个级别。但是,我的目标是避免使用静态方法(如果可行)。这也让我觉得我可能在Villolating SRP,但是这个对象的主要目标是它可以从xml字符串进行序列化/反序列化
在这种情况下使用静态方法有什么想法吗?我是否应该将ToXmlString
设置为非静态,而将FromXmlString
设置为静态?我应该创建一个只处理MyClass系列化的新类吗
编辑:
我在这里讨论的类是一个简单的传输对象。它用于保存/恢复第三方工具中的值
谢谢 如果需要标准序列化(XML或非XML),则两种序列化/反序列化方法都不应是静态的 在MyClass中,您应该重新定义“writeObject”和“readObject”,以替换默认的序列化方法。下面是关于这些方法的一个例子 如果您不想要“标准序列化”,那么使用静态方法对我来说很合适。静态方法不是异端邪说
PS:这不是问题,但是如果您想要WML序列化,您可以使用。FWIW我认为序列化是一个问题,应该与类的其余部分分开,尤其是如果您的类是业务类型的话 开发组件时的一般规则是确保它只处理少数关注点,并将业务关注点与技术关注点分开 如果以后需要从数据库或二进制格式管理序列化,该怎么办
您可能会以越来越多的技术方法(SaveToDB、LoadFromDB、ToBinaryStream、FromBinaryStream…)结束,这些方法会使您的类变得混乱,并使其越来越难以维护,从而隐藏其主要用途(例如业务)。详细阐述Benoit的答案,下面是一个示例,其中被序列化的类定义了序列化行为(我没有写这个):
注意使用transient to来描述不会被序列化的字段。我认为在静态和实例方面将互补方法分开并不可怕,因为框架偶尔会这样做(例如String.Split/Join) 尽管如此,我认为最小化静态方法的使用不是一个好主意。要避免的是静态可变状态,而不是静态方法。一个只对其参数而不是静态变量进行操作的静态方法纯粹是令人惊叹的 纯静态函数可以比实例方法更易于维护,因为实例方法不会以明显的方式通信它可以变异的实例字段。通过遵循不保持任何静态的规则,静态方法只能依靠其参数进行操作,因此可以更好地预测该方法在应用程序中的作用。这在多线程时尤为重要
由于ToXmlString方法应用于定义它的类的实例,其中一些注意事项不适用。它可以很容易地更改以秘密方式传递给它的对象的状态,因为它可以访问实例的所有私有成员。但我只是想说,作为一般规则,静态方法不是问题。您可以定义一个构造函数,它接受一个XMLReader(或者一个字符串,如果您确实坚持的话)。这样做的主要优点是,它允许您在类中拥有更强的不变量,并通过使用
只读来明确任何不可变成员。对于C#和Java,标准库中的约定是到_
方法是实例方法,而从
方法是静态的(必要时)。例如:ToString()
是一种实例方法。“真正的序列化”?你是说Jerod现在拥有的东西不是“真正的”?有很多非常有效的理由不使用标准的序列化机制。你是对的。“标准”世界比“真正的”好:我编辑了我的帖子来纠正这一点,谢谢。我之所以避免静态,是因为有一些小原因。1)如果需要,更容易转到IoC 2)通过继承扩展对象3)通过使用OO实践避免降级为God类。。。
// : c12:SerialCtl.java
// Controlling serialization by adding your own
// writeObject() and readObject() methods.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SerialCtl implements Serializable {
private String a;
private transient String b;
public SerialCtl(String aa, String bb) {
a = "Not Transient: " + aa;
b = "Transient: " + bb;
}
public String toString() {
return a + "\n" + b;
}
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(b);
}
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
stream.defaultReadObject();
b = (String) stream.readObject();
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
SerialCtl sc = new SerialCtl("Test1", "Test2");
System.out.println("Before:\n" + sc);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(buf);
o.writeObject(sc);
// Now get it back:
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(
buf.toByteArray()));
SerialCtl sc2 = (SerialCtl) in.readObject();
System.out.println("After:\n" + sc2);
}
}