Подтвердить что ты не робот

Должен ли объект записываться в файл или должен ли другой объект воздействовать на него для выполнения ввода-вывода?

ПРИМЕЧАНИЕ. Извините за длинный вопрос!

Я пытаюсь понять некоторые ключевые области, стоящие за объектной ориентацией, и я не мог так или иначе решить мой конкретный вопрос.

Скажем, у меня есть объект, полный прекрасных данных. Класс bob.

Bob myBob = new Bob("This string is data");

Скажем, я хочу сохранить содержимое myBob в xml файле (bob.xml)

Должен ли я заставить объект действовать на bob, чтобы написать содержимое, или мне нужно, чтобы myBob сделал это?

Случай 1: действие над объектом

Writer myWriter = new Writer(myBob, "C:\\bob.xml");

Случай 2: Сохранить метод

myBob.Save("C:\\bob.xml");

Некоторые люди поддерживают один вариант, поскольку это означает, что если код для записи файлов был изменен, ему не нужно обновлять каждый метод Save; Я предполагаю, что повторное использование кода повторится. Моя проблема заключается в получении всех данных из объектов, которые могут иметь личные данные без доступа.

Случай для второго варианта заключается в том, что метод действует только на данные, хранящиеся в объекте, и то, как он должен быть. Отсутствие помех от других объектов.

Или ответ на мой вопрос является одним из тех вопросов, которые зависят от случая? Если да, то откуда вы знаете, когда один метод предпочтительнее другого?

4b9b3361

Ответ 1

Правильный подход, в общем, является вашим примером 1. Это не несет ответственности за класс (независимо от того, что он делает), не связывая его с конкретным механизмом сохранения (диск).

Вы смотрите на конкретный случай более обобщенной проблемы: Сериализация. Хорошо и хорошо, если у объекта есть какие-то средства, чтобы указать, как он должен быть сериализован - это единственная сущность, которая знает, что нужно для десериализации. Но если вы сделаете объект сохраненным на диск, вы плотно связали этот объект с конкретной реализацией.

Вместо этого подумайте о создании интерфейса, который обобщенный "писатель" может использовать для "сериализации" объекта независимо от того, что сериализует сценарий. Таким образом, вы сможете сериализовать на диск, в сеть, в память, на то, что вам действительно нужно для сериализации.:)

Ответ 2

Я бы сделал Bob знать, как сериализовать себя, поскольку он имеет личные данные. Другой объект (например, ваш Writer) взял бы это и поместил бы его на диск. Боб знает, как лучше справляться с его данными, но ему не нужно заботиться о том, как и где оно хранится. Ваш Writer знает, как лучше сохранять данные, но не нужно заботиться о том, как эти данные создаются.

Ответ 3

Это пример того, как можно использовать Шаблон разработки стратегий. Ваш объект myBob может иметь экземпляр класса, который будет его выписывать. Вы можете захотеть, чтобы автор реализовал интерфейс или был получен из абстрактного класса, так что процедура сохранения может быть легко изменена.
Сегодня вы сохраняете в xml, но вам может понадобиться, в конечном итоге, сохранить объект в базе данных. Этот шаблон позволит вам легко изменить процедуру сохранения. У вас даже будет возможность изменить способ сохранения во время выполнения.

Ответ 4

Я предпочитал вариант 2; однако, поскольку я начал действительно пытаться понять и моделировать области, над которыми я работаю, я предпочитаю вариант 1.

Представьте себе, что ваши моделирующие транспортные средства. Почему автомобиль знал, как упорствовать? Он может знать, как двигаться, как начинать и как останавливаться, но что такое "Сохранить" в контексте транспортного средства.

Ответ 5

Другим способом является использование шаблона посетителя. Пусть ваш объект содержит метод Accept, который проходит через членов, которые вы хотите обработать/сериализовать, и чтобы посетитель был вашим сериализатором. Всякий раз, когда вы обновляете или изменяете сериализацию (обычный текст в xml для двоичного кода), вам не нужно обновлять объект.

У нас были хорошие впечатления на работе, делающие это так. Это довольно мощный.

Ответ 6

Я думаю, что правильный подход - это случай 1, но ваш класс может быть определен таким образом, чтобы использовать оба подхода:

class Bob {

    IWriter _myWriter = null;

    public Bob(){
        // This instance could be injected or you may use a factory
        // Note the initialization logic is here and not in Save method
        _myWriter = new Writer("c://bob.xml")
    }

    //...
    public void Save(){

        _myWriter.Write(this);    

    }
    // Or...
    public void Save(string where){

        _myWriter.Write(this, where);

    }
    //...
}

Это может быть легко изменено, чтобы поместить логику записи и инициализацию в базовый класс, чтобы класс Bob был еще более чистым и независимым от сохранения.

Ответ 7

Сделайте это:

public interface Writable {
    public void Save(Writer w);
}

public interface Writer {
    public void WriteTag(String tag, String cdata);
}

public class Bob : Writable {
    private String ssn = "123-23-1234";
    public void Save(Writer w) {
        w.WriteTag("ssn", ssn);
    }
}

public class XmlWriter : Writer {
    public XmlWriter(Sting filename) {...}
    public void WriteTag(String tag, Sting cdata) {...}
}

Очевидно, что это не полное решение, но вы должны получить общую идею.