2016-02-25 3 views
1

У меня проблема с сериализацией класса с использованием шаблона singleton. Во-первых, позвольте мне представить код:Сериализация с шаблоном проектирования Singleton

import java.io.ObjectStreamException; 
import java.io.Serializable; 

import org.ejml.simple.SimpleMatrix; 

public class Operation implements Serializable { 

    private static final long serialVersionUID = 1L; 

    private final static int CONSTANT = 10; 

    private SimpleMatrix data; 
    private Long timestamp; 

    private static Operation instance = new Operation(); 

    private Operation() { 
     data = new SimpleMatrix(1, CONSTANT); 
    } 

    protected static Operation getInstance() { 
     return instance; 
    } 

    //Hook for not breaking the singleton pattern while deserializing. 
    private Object readResolve() throws ObjectStreamException { 
      return instance; 
    } 


    protected void setData(SimpleMatrix matrix) { 
     this.data = matrix; 
    } 

    protected SimpleMatrix getData() { 
     return data; 
    } 

    public Long getTimestamp() { 
     return timestamp; 
    } 

    public void setTimestamp(Long timestamp) { 
     this.timestamp = timestamp; 
    } 
} 

У меня есть три проблемы с его в надежде, что кто-то может помочь мне:

  1. Насколько я знаю, статические поля не являются не сериализованная. Итак, если я десериализуюсь, это мое конечное статическое поле CONSTANT, установленное в 10? Если нет, как я могу это сделать? Это очень важно.

  2. Как вы можете видеть, в конструкторе создается новая матрица. Если я deserialize, мой data, который был перезаписан этим конструктором? Для десериализации я хочу data сериализованной версии, а не новую матрицу. Конструктор мне нужен только первый раз перед сериализацией, чтобы создать экземпляр объекта.

  3. Прежде чем я начну сериализовать, я установлю поле timestamp ко времени сериализации. После десериализации я хотел бы сравнить это поле с меткой времени некоторых файлов (чтобы увидеть, изменились ли файлы после сериализации). Какую временную метку следует использовать как для времени сериализации, так и для последнего измененного времени файлов, чтобы я мог легко сравнивать?

+0

Это не очень понятно, почему вы должны сериализовать операции одиночки Но я хотел бы предложить:. Сериализовать только (кажется, что это единственное, что когда-либо меняется в синглетоне), и просто позвольте синглету строить нормально. Или даже лучше, не используйте синглтон, используйте инъекцию зависимостей;) –

+0

@PierreHenry С помощью операции это было просто пример. Да, меняет только матрица. Как я могу только сериализовать матрицу, а потом десериализовать матрицу обратно в синглтон? – machinery

+0

@PierreHenry Мне также нужно знать ialize timestamp. – machinery

ответ

1
  1. Статическая константа связана с классом, так сериализации и десериализации экземпляра не влияет вообще.

  2. Для десериализации работать, вам необходимо установить данные одноэлементные к данным десериализованным например:

    private Object readResolve() throws ObjectStreamException { 
        instance.setData(getData()); 
        return instance; 
    } 
    
  3. Отметка может остаться как Лонг, это прекрасно. Используйте System.currentTimeMillis(), вы сможете сравнить с датой lastModified() объекта File. Просто установите в поле, когда вы сериализации:

    private void writeObject(java.io.ObjectOutputStream out) 
        throws IOException{ 
        timestamp=System.currentTimeMillis(); 
        out.defaultWriteObject(); 
    } 
    

тест я сделал, чтобы быть уверенным, что я говорю, используя строку вместо матрицы, как в вашем коде:

public static void main(String[] args) throws Exception { 
    Operation op=getInstance(); 
    op.setData("test1"); 
    byte[] ds=serialize(); 
    System.out.println(new Date(getInstance().timestamp)); 
    op.setData("test2"); 
    deserialize(ds); 
    System.out.println(getInstance().getData()); 

} 

Это дает мне текущую дату и test1, так как экземпляр deserialize переопределяет текущий экземпляр. serialize и deserialize просто конвертировать между экземпляром и байтами.

+0

Благодарим вас за ответ. У меня есть вопрос ко второму вопросу. Мне также нужно добавить instance.setTimestamp (getTimestamp()); если я делаю временную метку приватной и внедряю сеттер и геттеры? Смотрите мой измененный код в моем сообщении. – machinery

+0

Да, конечно, я не делал этого в своем коде, но вы также должны установить временную метку. –

0

Я бы предположил, что вы принимаете подход для внедрения синглтонов, поскольку обработка сериализации будет выполняться бесплатно. В вашем случае это будет

public enum Operation { 
    INSTANCE; 
    // No need to handle Serialization 
} 

Цитирование Джошуа Блох в Effective Java "типа перечисления Одноэлементного является лучшим способом реализации синглтона. "

Есть много преимуществ такого подхода, вы можете узнать here
А также For instance control, prefer enum types to readResolve

Смежные вопросы