3

少し主観的かもしれませんが、私の現在の状況についてご意見をお聞かせください。オブジェクトのシリアル化/逆シリアル化に使用されるクラスがあります。

public class MyClass
{
    public static string ToXmlString( MyClass c ) { /*...*/ }
    public static MyClass FromXmlString( string xml ) { /*...*/ }
}

私がこのアプローチを気に入っているのは、2 つの機能を同じレベルに保つためです。ただし、私の目標は、静的メソッドの使用を避けることです (実行可能な場合)。SRP に違反しているようにも感じますが、このオブジェクトの主な目的は、xml 文字列からシリアライズ/デシリアライズできるようにすることです。

この状況での静的メソッドの使用について何か考えはありますか? ToXmlString非静的にするだけで、FromXmlString静的のままにする必要がありますか? MyClass のシリアル化のみを処理する新しいクラスを作成する必要がありますか?

編集:

ここで説明するクラスは、単純な転送オブジェクトです。サードパーティ製ツールから値を保存/復元するために使用されます。

ありがとう!

4

6 に答える 6

2

FWIWクラスがビジネスタイプの場合、シリアライゼーションはクラスの残りの部分から分離する必要がある問題だと思います。

コンポーネントを開発する際の一般的なルールは、少数の懸念事項のみに対処し、ビジネス上の懸念事項を技術的な懸念事項から分離することです。

後でデータベースまたはバイナリ形式からシリアル化を管理する必要がある場合はどうすればよいでしょうか?

クラスを乱雑にし、その主な目的 (ビジネスなど) を隠して保守をますます難しくする、ますます技術的なメソッド (SaveToDB、LoadFromDB、ToBinaryStream、FromBinaryStream...) で終わる可能性があります。

于 2010-08-16T16:58:40.903 に答える
1

C#とJavaの両方の標準ライブラリの規則では、To__メソッドはインスタンスメソッドであり、From__メソッドは静的です(必然的に)。例:ToString()はインスタンスメソッドです。

于 2010-08-23T21:16:38.510 に答える
0

フレームワークが時折これを行うので(たとえば、String.Split / Join)、静的メソッドとインスタンスに関して補完的なメソッドを分離することはそれほどひどいとは思いません。

しかし、そうは言っても、静的メソッドの使用を最小限に抑えるという目標は良い考えではないと思います。避けるべきことは、静的メソッドではなく、静的な可変状態です。静的変数ではなく、そのパラメーターのみを操作する静的メソッドは、純粋な素晴らしさです。

インスタンスメソッドは、変更できるインスタンスフィールドを明確に伝達しないため、純粋な静的関数はインスタンスメソッドよりも保守しやすくなります。静的状態は一切維持されないというルールに従うことで、静的メソッドはそのパラメーターのみを操作することに依存できるため、アプリケーションでのメソッドの役割をより適切に予測できます。これは、マルチスレッドの場合に特に重要です。

ToXmlStringメソッドは、それが定義されているクラスのインスタンスに適用されているため、これらの考慮事項の一部は適用されません。インスタンスのすべてのプライベートメンバーにアクセスできるため、渡されるオブジェクトの状態を手に負えない方法で簡単に変更できます。しかし、私は、原則として静的メソッドは問題ではないと言うことを意味します。

于 2010-08-16T17:14:11.770 に答える
0

Benoit's answer について詳しく説明すると、シリアル化されているクラスがシリアル化の動作を定義する例を次に示します (私はこれを書きませんでした)。

// : 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);
  }
}

シリアル化されないフィールドを記述するために、transient を使用していることに注意してください。

于 2010-08-16T17:02:43.993 に答える
0

XMLReader (またはどうしても主張する場合は文字列) を取るコンストラクターを定義できます。これの主な利点は、クラスでより強力な不変条件を使用できるようになり、readonly.

于 2010-08-16T17:16:45.680 に答える
0

標準のシリアル化 (XML であろうとなかろうと) が必要な場合は、シリアル化/逆シリアル化の両方のメソッドを静的にしないでください。

MyClass では、「writeObject」と「readObject」を再定義して、デフォルトのシリアル化メソッドを独自のものに置き換える必要があります。これらのメソッドに関するSun のチュートリアルを次に示します。

「標準のシリアル化」が必要ない場合は、静的メソッドを使用しても問題ないようです。静的な util メソッドは異端ではありません。

PS : それは問題ではありませんが、WML シリアル化が必要な場合は、XStream APIを使用できます。

于 2010-08-16T16:55:15.857 に答える