Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.12.05;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.57 MB
Время: 0.04 c
3-1099669249
denis24
2004-11-05 18:40
2004.12.05
qrdbtext.wordwrap


1-1101049636
Frozzen
2004-11-21 18:07
2004.12.05
Canvas.Poligon(Points: array ofTPoint);


1-1100968084
lp
2004-11-20 19:28
2004.12.05
Grid


1-1101325190
BuG
2004-11-24 22:39
2004.12.05
Как сделать так, чтобы появлялась форма-заставка, пока программа


1-1100766513
Chery
2004-11-18 11:28
2004.12.05
Клиент не работает под WinXP . Cервер- Midas, Socket.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский