Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.12.05;
Скачать: CL | DM;

Вниз

Singleton   Найти похожие ветки 

 
Fktrc ©   (2004-11-23 05:10) [0]

Можно ли в Delphi создать единственный экземпляр класса на все приложение? Т.е. чтобы при попытках создать второй выдавалась либо ошибка компиляции, либо рантайм ошибка. По-моему, такие объекты называют singleton, хотя могу и ошибаться.
Пока приходит в голову только создание какого-л именованного объекта ядра в конструкторе объекта. Но нет ли другого способа, изящнее?


 
MBo ©   (2004-11-23 07:19) [1]

Один из путей реализован в модуле ClipBrd для ClipBoard


 
Bel ©   (2004-11-23 09:45) [2]

Можно.
Можно еще вместо ошибки при попытке создания второго экземпляра подменить его уже созданным первым экземпляром. Надо перекрыть методы NewInstance и FreeInstance. Ну, и счетчик ссылок на объект.


 
Fktrc ©   (2004-11-23 09:53) [3]

2Bel
Примерчик перекрытия методов NewInstance и FreeInstance или ссылку на таковой можете дать? А я пока по гуглю и яндексу побегаю...


 
Bel ©   (2004-11-23 10:23) [4]

Держи, разбирайся. Когда-то сам копался с этим.

unit uSingleton;

interface

type
  TSingleton = class (TObject)
  private
    FCount: Integer;
  public
    class function NewInstance: TObject; override;
    procedure FreeInstance; override;
    function Test1(SomeText: String): Integer;
    function Test2(SomeText: String): Integer;
  end;

implementation

uses Dialogs, SysUtils;

var
  gSingle: TSingleton;

class function TSingleton.NewInstance: TObject;
begin
  if gSingle <> nil then begin
    Result := gSingle;
    Inc(gSingle.FCount);
  end else begin
    Result := inherited NewInstance;
    gSingle := TSingleton(Result);
    gSingle.FCount := 1;
  end;
end;

procedure TSingleton.FreeInstance;
begin
  if FCount = 0 then begin
    inherited;
    gSingle := nil;
  end else
    Dec(FCount);
end;

function TSingleton.Test1(SomeText: String): Integer;
begin
  ShowMessage(SomeText + ": Test1 adr: " + IntToStr(Integer(Self)) + " counter: " + IntToStr(FCount));
  Result := 1;
end;

function TSingleton.Test2(SomeText: String): Integer;
begin
  ShowMessage(SomeText + ": Test2 adr: " + IntToStr(Integer(Self)) + " counter: " + IntToStr(FCount));
  Result := 2;
end;

end.


 
Bel ©   (2004-11-23 10:30) [5]

:)  Только сейчас увидел, что в FreeInstance косяк со счетчиком. Ну да ладно, сам разберешься.


 
Amoeba ©   (2004-11-23 10:33) [6]

На сайте "Королевство дельфи" http://www.delphikingdom.com найдешь статью, специально посвященную этому вопросу.


 
Reindeer Moss Eater ©   (2004-11-23 10:37) [7]

Пока приходит в голову только создание какого-л именованного объекта ядра в конструкторе объекта. Но нет ли другого способа, изящнее?

Есть один класс и один его конструктор и один паскалевский модуль в котором все это реализовано. И глобальные переменные модуля на весь процесс.

Какие ядра? Какие пушки?
Есть способ не изящнее, а проще.


 
Fktrc ©   (2004-11-23 10:47) [8]

Принято к сведению.
Всем спасибо.


 
KSergey ©   (2004-11-23 11:07) [9]

Вообще, как как-то сказал Reindeer Moss Eater ©, "модуль в паскале - и есть уже синглетон! Зачем изобретать что-то еще??"
И я с ним согласен ;)


 
Суслик ©   (2004-11-23 11:49) [10]

Мне всегда хватало

tsingleton = class
  class function SomeFunction: Integer;
  class procedure SomeProcedure();
  ...
end;


Значения можно хранить под implementation.

Использовать TsingleTon.SomeProcedure.

Отличие от singleton в том, что мой tsingleton всегда есть ровно онид по определению и его убить нельзя.


 
Palladin ©   (2004-11-23 11:52) [11]

Он не прав. Singletone это во-первых, контроль самого программиста. Модуль не есть Singletone. Класс объявлен, в interface, можно создать сколько угодно объектов этого класса. Другое дело когда при вызове конструктора возвращается один и тот же объект. Это и есть Singletone.

Clipboard, это не Singletone. Так же как и Application. Что бы модуль превратить в Singletone в Interface нужно объявить только функции работы. Но это уже не Singletone в понятии OOD&P.


 
Суслик ©   (2004-11-23 12:02) [12]

Может ли мне кто-нибудь объяснить смысл делать в дельфи singleton?


 
Palladin ©   (2004-11-23 12:05) [13]

при чем тут делфи, это вопрос проектирования... воспользуйся поисковиком и найди описание singletone... там будет объяснение...


 
Суслик ©   (2004-11-23 12:14) [14]


>  [13] Palladin ©   (23.11.04 12:05)

Вопрос проектирования говоришь...
Ну-ну.
Вот только изначальный вопрос тут не на концептуальном уровне, а на уровне реализации. Причем, реализации на конкретном языке. Вот и вопрос, зачем нужно в дельфи иметь singleton.

Songleton в теории обычно идут в связке с другими типовыми решениями. Например, abstract factory. Вопрос, зачем нужно в рамках дельфи делать singleton да и фабрику ту же, когда есть виртуальные классовые методы.

Заметь, я не говорю про проектирование. Я говорю, про реализацию, зачем в конкретном языке городить огород, когда можно, например, в случае фабрики и singleton сделать так:

type
  TMyFactory = class
     public class function CreateFirstObject: TObject; virtual; abstract;
     public class function CreateSecondObject: TObject; virtual; abstract;
  end;

  TFirstFactory = class (TMyFactory)
      public class function CreateFirstObject: TObject; override;
      public class function CreateSecondObject: TObject; override;
  end;

implementation

class function TFirstFactory.CreateFirstObject: TObject; override;
begin
   Result := TFistObject.Create;
end;

class function TFirstFactory.CreateSecondObject: TObject; override;
begin
   Result := TSecondObject.Create;
end;

end.


В качестве фабрики можешь описывать TMyFactory, а передавать TFirstFactory. Чем не фабрика? Концептуально именно она. ЧЕм не singleton? Концептуально именно он. Спустившись на уровень реализации задай себе вопрос, зачем тебе нужна именно такая реалзиация singleton через NewInstance и FreeInstance?


 
KSergey ©   (2004-11-23 12:16) [15]

> [11] Palladin ©   (23.11.04 11:52)

Да, модуль - это безусловно не класс-синглетон. Речь шла об идейной замене, а не буквальной.

Т.е. модуль есть един, и он - есть без нашего участия. Так есть ли смысл изобретать что-то?

>  Что бы модуль превратить в Singletone в Interface нужно
> объявить только функции работы.

Да, конечно.

> Но это уже не Singletone в понятии OOD&P.

Буквально - нет. По сути - от чего же?


 
Reindeer Moss Eater ©   (2004-11-23 12:17) [16]

Автору вопроса нужен был единственный экземпляр класса.
И автор робко предположил, что то что он хочет называется singleton.

Как этого достичь, ему сказали.
При чем здесь то, что это не singlrton?


 
Суслик ©   (2004-11-23 12:19) [17]


> [15] KSergey ©   (23.11.04 12:16)

Насколько я понимаю, что все-таки модуль нельзя использовать как singleton именно потому, что мудули не могут использоваться в рамках полиморфизма.
Мое же видение singleton через классовые сслыки вполне укладываться в рамки полиформизма.


 
Суслик ©   (2004-11-23 12:20) [18]


>  [16] Reindeer Moss Eater ©   (23.11.04 12:17)

не вижу проблемы в том, что приводится другое видение данного вопроса...


 
Reindeer Moss Eater ©   (2004-11-23 12:21) [19]

Вопрос бы в единственном экземпляре на процесс.


 
Palladin ©   (2004-11-23 12:32) [20]

Фабрика фабрикой. Это конкретная реализация. Это конкретный пример. Можно обойтись и без singletone.

А я разработал свой шаблон в котором Singletone нужен и без него не обойтись. Или у меня в программе создан механизм при котором без Singletone тоже не обойтись... Простейший пример: класс для работы с ресурсом, доступ к котрому должен производится только из одного экземпляра класса, другие экземпляры недопустимы. Это Singletone.


 
Palladin ©   (2004-11-23 12:35) [21]


> [15] KSergey ©   (23.11.04 12:16)

В таком случае заголовочные файлы c тоже Singletone.


 
Суслик ©   (2004-11-23 12:36) [22]


> Это Singletone.

пиши через классовые методы (class procedure и пр.), обращаясь к ним через класс:

TRecource.Write(...)
..
TRecource.Read(...)


тоже singleton..


 
Palladin ©   (2004-11-23 12:37) [23]

Если речь идет об идейной замене, а не буквальной. :)


 
Суслик ©   (2004-11-23 12:40) [24]


>  [23] Palladin ©   (23.11.04 12:37)

что такое "буквальной"?

С языках, на основе которой пишет Гамма свою знаменитую книга, если не ошибаюсь, нет виртуальных статических методов!
Т.е. методов
class function F: Integer; virtual;

Поэтому в тех языках нужно делать именно так, как написано в книге.

В дельфи есть штатных механизм фабрик и singleton. Да, он не очень похож на примеры из книги. НО делает ровно тоже самое.


 
Palladin ©   (2004-11-23 12:41) [25]


> [22] Суслик ©   (23.11.04 12:36)

Да это и ежу понятно. Вот только, в делфи есть классовые методы, но нет классовых полей.

Что то на подобие Singletone можно получить, запихав конструктор в private или protected (вместе с деструктором) написать толпу классовых методов и описать в implementation "поля" класса... в таком случае идейная замена выйдет неплохая.


 
Palladin ©   (2004-11-23 12:42) [26]


> что такое "буквальной"?

Это вопрос к KSergey, а не ко мне...


 
Суслик ©   (2004-11-23 12:47) [27]


>  [25] Palladin ©   (23.11.04 12:41)


> запихав конструктор в private

а ты попробуй :)))
Create, идущий от TObject не запихаешь никуда - все равно, собака, виден :))

Отдестроить объект любому клиенту в дельфи помешать нельзя :)))
Хоть обзасовывайся деструктор куда угодно.

С сях можно, в java можно - в дельфи нет.


> но нет классовых полей.

А знаешь почему? Потому, как в отличие от си++ и java статические (классовые методы) в дельфи могут быть виртуальны. Отседова ограничение на статические переменные.


 
Palladin ©   (2004-11-23 13:02) [28]


> а ты попробуй :)))



Unit Singletone;
Interface
Type
TSingletone=Class
 Protected
  Constructor Create;
  Destructor Destroy;
 Public
  Class Function New:TSingletone;
  Class Procedure Free;
End;

Implementation

Var
SingleObject:TSingletone;

Class Function TSingletone.New;
Begin
If SingleObject=Nil Then SingleObject:=TSingletone.Create;
Result:=SingleObject;
End;

Constructor TSingletone.Create;
Begin
End;

Class Procedure TSingletone.Free;
Begin
End;

Initialization
SingleObject:=Nil;
End.


Ну вот, попробовал... в этом модуле будет видно, в других нет...
хоть заудаляйся...


> А знаешь почему?

Спасибо за разьяснения... даже и в голову не приходило... года три назад...


 
Суслик ©   (2004-11-23 13:06) [29]


>  [28] Palladin ©   (23.11.04 13:02)


> Ну вот, попробовал... в этом модуле будет видно, в других
> нет...
> хоть заудаляйся...

ты сам проверял, что написал?
Кто не будет виден в другом модуле?
Все видно :)


 
Суслик ©   (2004-11-23 13:09) [30]


> [28] Palladin ©   (23.11.04 13:02)

у тебя create виден, только не tsingletone, а tobject.

Спасти свой класс от инстанцирования тебе не удасться :)
Кроме как переопределить в PUBLIC конструктор Create, в нем возбуждать исключение, а пользоваться другим private конструктором.


 
Palladin ©   (2004-11-23 13:10) [31]

Я пробовал что написал. Не видно. D6


 
Palladin ©   (2004-11-23 13:11) [32]


> Кто не будет виден в другом модуле?

Конструктор от TObject.


 
Суслик ©   (2004-11-23 13:12) [33]


>  [31] Palladin ©   (23.11.04 13:10)


> Я пробовал что написал. Не видно. D6

ну бог в помощь :)
Для справки: в дельфи не документированно понижение видимости. В д3 оно было, но работало не так, как в д5. Если не ошибаюсь и в д6 нет документации на понижение видимости. Если найдешь оное, буду благодарен за информацию.


 
Суслик ©   (2004-11-23 13:15) [34]


>  [32] Palladin ©   (23.11.04 13:11)


> Конструктор от TObject.

гонишь :)))

Как раз он то и будет виден. Твой новый конструктор виден не будет.


 
Palladin ©   (2004-11-23 13:21) [35]

Хем, ну что ж... ты понизил абстрагирование обсуждения Singletone до Делфи, я в свою очередь понизил до Делфи6... :)


 
Суслик ©   (2004-11-23 13:23) [36]


>  [35] Palladin ©   (23.11.04 13:21)
> Хем, ну что ж... ты понизил абстрагирование обсуждения Singletone
> до Делфи, я в свою очередь понизил до Делфи6... :)


Точное замечание:)


 
GuAV ©   (2004-11-23 13:25) [37]

Palladin ©   (23.11.04 13:02) [28]
Ха! FreeAdnNil его сделает! :)


 
Palladin ©   (2004-11-23 13:35) [38]

Не сделает, не волнуйся.


 
Palladin ©   (2004-11-23 13:37) [39]

Сорри, а ведь точно сделает...


 
jack128 ©   (2004-11-23 13:41) [40]

Palladin ©   (23.11.04 13:37) [39]
и создать твой объект можно. Через классовую ссылку ;-)


 
Palladin ©   (2004-11-23 13:43) [41]

Ну и хрен с ним...


>  [40] jack128 ©   (23.11.04 13:41)

через какую классовую ссылку?


 
jack128 ©   (2004-11-23 14:09) [42]

var
 cl: TClass;
begin
 cl := TSingletone;
 with cl.Create do
   ...  
end;


 
Суслик ©   (2004-11-23 14:15) [43]


>  [42] jack128 ©   (23.11.04 14:09)

create должен быть virtual
иначе создаться объект класса tsingletone, но выполниться тело конструктора tobject


 
jack128 ©   (2004-11-23 14:45) [44]

Суслик ©   (23.11.04 14:15) [43]
Спасибо, что напомнил ;-) Но в данном случае это не имеет значение.


 
VMcL ©   (2004-11-23 15:34) [45]

>>Palladin ©  (23.11.04 13:37) [39]

Даже без FreeAndNil.
TObject(SingleObject).Free;
:-p


 
Palladin ©   (2004-11-23 15:41) [46]

Это проблема TObject :) Я не виноват что в нем Free невиртуальный :)


 
Суслик ©   (2004-11-23 15:43) [47]


> Это проблема TObject :)

это не проблема tobject, это особенность дельфи - нет понижения видимости.
Может это и к лучшему...



Страницы: 1 2 вся ветка

Текущий архив: 2004.12.05;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.03 c
1-1101094265
zzTop
2004-11-22 06:31
2004.12.05
Подключение баз KAV к воей программе


14-1100074668
Суслик
2004-11-10 11:17
2004.12.05
Где купить delphi6 со всеми сервис паками?


4-1098041253
Jetus
2004-10-17 23:27
2004.12.05
Как правильно сохранить иконку?


14-1100693022
infom
2004-11-17 15:03
2004.12.05
Кто нидь в этом участвет ?


9-1090574993
Megabyte-CeerCop
2004-07-23 13:29
2004.12.05
Игра готова