Текущий архив: 2004.12.19;
Скачать: CL | DM;
Вниз
Читаю "Паттерны...". Есть вопрос. Найти похожие ветки
← →
Мирон © (2004-12-02 00:15) [0]В книге, как назло, все примеры приведены на сях.
В общем, добрался до паттерна "Singleton". В описании достоинств паттерна есть такая фраза: "поскольку класс Singleton инкапсулирует свой единственный экземпляр, он полностью котролирует то, как и когда клиенты получают доступ к нему".
описание класса:class Singleton {
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
};
реализация:Singleton* Singleton::_instance = 0;
Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
};
Получается, что в дельфи такой трюк провернуть нельзя, и все равно придется заводить глобальную переменную под экземпляр класса?
← →
DiamondShark © (2004-12-02 00:18) [1]
> Получается, что в дельфи такой трюк провернуть нельзя
В дельфи такой трюк не нужен.
В дельфи есть МОДУЛЬ. Это и есть синглетон.
(точнее, наоборот, синглетон -- это костыль для уродских языков, в которых отсутствует понятие модуля)
← →
Мирон © (2004-12-02 00:26) [2]DiamondShark © (02.12.04 0:18) [1]
М-м-м... Ладно, пойду спать, утром еще раз подумаю...
← →
uw © (2004-12-02 00:29) [3]
type
TSingleton = class
class function Instanse: TSingleton;
end;
class function TSingleton.Instanse: TSingleton;
const
First: Boolean = True;
Singleton: TSingleton = nil;
begin
if not Assigned(Singleton) then
Singleton := TSingleton.Create;
Result := Singleton;
end;
← →
uw © (2004-12-02 00:30) [4]First не нужен.
← →
uw © (2004-12-02 00:44) [5]>DiamondShark © (02.12.04 00:18) [1]
Синглтон играет роль, не связанную с модульностью. Пример. У меня есть контроллер, а в нем - пара устройств, управляемых по интерфейсу I2C. Пишу класс I2C. От него наследую два класса. К устройствам обращение идет асинхронно из разных процессов. Разделение ресурсов - через мьютекс. Определяю его как статический член и наблюдаю, что экземпляр класса уже работает, а мьютекс еще не создался. Проблема решается вписыванием мьютекса в синглтон.
← →
jack128 © (2004-12-02 00:45) [6]uw © (02.12.04 0:29) [3]
Singleton все таки должна быть глобальной, а не локальной константой ;-)
Но вообще в твоей реализации ничего не помешает мне создать сколько угодно экземпляров TSingleton. Нужно перекрывать NewInstance и FreeInstance.
← →
uw © (2004-12-02 00:48) [7]>jack128 © (02.12.04 00:45) [6]
У меня Singleton - типизированная константа. Она живет всегда, и создается один раз.
← →
GuAV © (2004-12-02 00:50) [8]Уже была ветка. И там показанно что создавать и убивать класс не запретишь.
← →
uw © (2004-12-02 00:54) [9]А, понял, о чем вы. Но классовая функция-то всегда будет возвращать один и тот же экземпляр. Аналог примера на C++.
← →
Игорь Шевченко © (2004-12-02 00:57) [10]uw © (02.12.04 00:54) [9]
Но мне кажется на первый взгляд, что от такого класса нельзя создать цепочку наследников, каждый из которых будет порождать свой уникальный instance. Или я ошибаюсь ?
← →
GuAV © (2004-12-02 00:58) [11]uw © (02.12.04 0:54) [9]
Но классовая функция-то всегда будет возвращать один и тот же экземпляр.
А мне кажется что она даже не скомпилитсяconst
First: Boolean = True;
Singleton: TSingleton = nil;
begin
if not Assigned(Singleton) then
Singleton := TSingleton.Create;
Result := Singleton;
← →
uw © (2004-12-02 01:00) [12]>Игорь Шевченко © (02.12.04 00:57) [10]
Так в этом и смысл - чтобы все наследники I2C разделяли этот ресурс с помощью единственного мьютекса.
← →
Игорь Шевченко © (2004-12-02 01:00) [13]jack128 © (02.12.04 00:45) [6]
С перекрытием NewInstance тоже самое, что и в [10], на мой взгляд.
Ситуация такова - имеется некий базовый класс, обладающий свойством Singleton. Хочется иметь от него наследников, каждый из которых будет порождать гарантированно единственный экземпляр для каждого конкретного типа наследника.
← →
Игорь Шевченко © (2004-12-02 01:03) [14]GuAV © (02.12.04 00:58) [11]
> А мне кажется что она даже не скомпилитсяtype
TSingleton = class
public
class function Instance: TSingleton;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TSingleton }
{$WRITEABLECONST ON}
class function TSingleton.Instance: TSingleton;
const
FInstance: TSingleton = nil;
begin
if FInstance = nil then
FInstance := TSingleton.Create;
Result := FInstance;
end;
{$WRITEABLECONST OFF}
procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessageFmt("Instance = %.8x", [Integer(TSingleton.Instance)]);
end;
И чего бы ей не скомпилиться ?
← →
GuAV © (2004-12-02 01:10) [15]Игорь Шевченко © (02.12.04 1:03) [14]
{$WRITEABLECONST ON}
Забыл уже что такое бывает :(
Хотя тогда интересно получается - локальная константа хранит значение между вызовами функции... имхо следует всёже назвать её глобальной переменной. Хотя признаю что ошибся, скомпилится.
← →
DiamondShark © (2004-12-02 02:05) [16]
> Так в этом и смысл - чтобы все наследники I2C разделяли
> этот ресурс с помощью единственного мьютекса.
Мьютекс в implementation секции модуля. Инициализация мьютекса в initialization.
Какой ещё огород надо городить?
К тому и пришли: искомый синглетон -- это модуль.
← →
jack128 © (2004-12-02 02:22) [17]Игорь Шевченко © (02.12.04 1:00) [13]
Хочется иметь от него наследников, каждый из которых будет порождать гарантированно единственный экземпляр для каждого конкретного типа наследника
Так естественно не будет. Будет один экземпляр на всю иерархию. Но достаточно легко сделать так как хотите вы, достаточно завести массив
Singletons: array of record SingletonClass: TSingletonClass; Instance: TSingleton; RefCount: Integer end;
и в NewInstance проверять, создан ли экземпляр соответствующего класса.
← →
jack128 © (2004-12-02 03:43) [18]DiamondShark © (02.12.04 2:05) [16]
К тому и пришли: искомый синглетон -- это модуль.
модуль - это силенгтон. Но не всякий силенгтон - модуль. Можно использовать модуль как силегтон, но не обязательно. Когда требуется наследование или полиморфизм, нужно воспользоваться классами.
← →
iZEN © (2004-12-02 08:24) [19]Кстати, статья с обсуждением Singleton здесь:
http://www.rsdn.ru/Forum/Message.aspx?mid=836726&pg=1
← →
Игорь Шевченко © (2004-12-02 10:21) [20]jack128 © (02.12.04 02:22) [17]
Неудобно
← →
Суслик © (2004-12-02 10:47) [21]не вижу смысла иметь реализацию singleton в дельфи через всякие тонкости типа NewInstance.
Модуль + классовые ссылки = чем не singleton?
← →
Суслик © (2004-12-02 10:49) [22]
> [18] jack128 © (02.12.04 03:43)
> Когда требуется наследование или полиморфизм, нужно воспользоваться
> классами.
или классовыми ссылками и соответственно классовыми методами (class procedure). Такие методы также могут быть виртуальными и абстрактными. В отличие, кстати сказать, от java и c++ - там классовые методы называются "статические" и они полностью оправдывают свое название.
← →
vuk © (2004-12-02 11:02) [23]to Игорь Шевченко © (02.12.04 01:00) [13]:
>Ситуация такова - имеется некий базовый класс, обладающий
>свойством Singleton. Хочется иметь от него наследников, каждый
>из которых будет порождать гарантированно единственный экземпляр
>для каждого конкретного типа наследника.
Перекрываем NewInstance, но созданный экземпляр храним не в переменной а в коллекции, по одному на каждый класс. При попытке создания производится поиск в коллекции.
← →
Суслик © (2004-12-02 11:05) [24]
> Перекрываем NewInstance, но созданный экземпляр храним не
> в переменной а в коллекции, по одному на каждый класс
(добавка) класс можно идентифицировать хоть по имени и хранить в хеше.
У меня примерно такая реализация создания уникального хранилища per class.
← →
vuk © (2004-12-02 11:10) [25]to Суслик © (02.12.04 11:05) [24]:
>класс можно идентифицировать хоть по имени и хранить в хеше
Как идентифицировать - это дело разработчика. Можно по имени, можно по ссылке на класс...
← →
Суслик © (2004-12-02 11:14) [26]
> [25] vuk © (02.12.04 11:10)
ну это я типа, чтобы поконкретней было :))
В первой версии у меня каждый класс обязан был перекрывать class function Id: integer; virtual; Фактически это был индекс в таблице. Дурацкая была затея. Потом отказался в пользу хеша.
← →
Игорь Шевченко © (2004-12-02 11:15) [27]vuk © (02.12.04 11:02) [23]
Пожалуй, оптимальный способ.
← →
jack128 © (2004-12-02 13:32) [28]Игорь Шевченко © (02.12.04 11:15) [27]
vuk © (02.12.04 11:02) [23]
Что то я не понял, чем способ vuk"a отличается от моего? И чем мой не удобен? Кодируется в 10 строк.
Страницы: 1 вся ветка
Текущий архив: 2004.12.19;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.027 c