Вопрос

Кажется, я мысленно застрял в дилемме модели наилегчайшего веса.

Во-первых, допустим, у меня есть одноразовый тип. DisposableFiddle и фабрика FiddleFactory:

public interface DisposableFiddle : IDisposable
{
    // Implements IDisposable
}

public class FiddleFactory
{
    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns a newly created fiddle.
    }
}

Тогда, по моему мнению, клиенту совершенно ясно, FiddleFactory что фабрика не претендует на право собственности на созданную скрипку и что клиент несет ответственность за уничтожение скрипки после ее завершения.

Однако вместо этого предположим, что я хочу разделить скрипки между клиентами, используя шаблон «Милегвес»:

public class FiddleFactory
{
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;        

    public DisposableFiddle CreateFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns an existing fiddle if a corresponding s is found,
        // or a newly created fiddle, after adding it to the dictionary,
        // if no corresponding s is found.
    }
}

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

Проблема на самом деле в том, что я звоню на фабрику FiddleFactory вместо, скажем, FiddlePool, и метод «создания» CreateFiddle вместо GetFiddle?Так:

public class FiddlePool : IDisposable
{
    private Dictionary<SomethingThatDifferentiatesFiddles, DisposableFiddle> fiddles = new ...;        

    public DisposableFiddle GetFiddle(SomethingThatDifferentiatesFiddles s)
    {
        // returns an existing fiddle if a corresponding s is found,
        // or a newly created fiddle, after adding it to the dictionary,
        // if no corresponding s is found.
    }

    // Implements IDisposable
}

Тогда клиенту станет яснее, что он не будет владеть возвращенной скрипкой, и ответственность за утилизацию скрипок лежит на пуле.

Или это можно легко решить только с помощью документации?

Есть ли выход из дилеммы?Есть ли вообще дилемма?:-)

Это было полезно?

Решение

Я вижу два выхода из этой проблемы:

  • Стиль ThreadPool:перепроектировать классы так, чтобы FiddlePool предоставляет интерфейс для выполнения сложных действий.Бассейн не раздает Fiddle экземпляры, потому что он имеет FiddlePool.PlayFiddle вместо этого метод.Поскольку пул контролирует время жизни скриптов, он отвечает за их удаление.

  • Стиль SqlConnection:изменить Fiddleобщедоступный метод удаления, так что он на самом деле просто возвращает скрипки в пул скрипок (который инкапсулирует класс скрипки).Внутренне, пул скрипок заботится о Действительно высвобождение одноразовых ресурсов.

Другие советы

Я согласен с вашим вторым мнением.Термины «Объединить» и «Получить» действительно проясняют ситуацию для потребителя.Тем не менее, он все еще не проясняет ситуацию достаточно ясно, и всегда следует добавлять документацию, чтобы обеспечить полное и достоверное понимание.

Вам следует сделать нечто большее, чем просто документацию и методы именования, чтобы сообщить клиентам, что им не следует вызывать Dispose.На самом деле было бы лучше, чтобы клиенты вызывали Dispose, поэтому создайте этот шаблон использования.Возьмите некоторое направление от создания наших пулов подключений к базе данных.

База данных объединяет множество соединений, которые сами поддерживают пул.Вызывающий код создает соединение, открывает его и вызывает для него закрытие (удаление).Вызывающий код даже не знает, объединен он в пул или нет, все это обрабатывается внутри класса соединения.При объединенном соединении вызов Open() игнорируется, если соединение уже открыто.Вызывается Close()/Dispose(), и в случае соединения в пуле это фактически возвращает соединение обратно в пул, а не закрывает его.

Вы можете сделать то же самое, создав класс PooledFiddle, который переопределяет Dispose и возвращает объект в пул.В идеале клиент даже не должен знать, что это объединенный Fiddle.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top