O artigo descreve como criar uma classe que segue o padrão único. A classe descrita vai cuidar do filho único requisitos e os efeitos em si, efetivamente deixando o programador para usar a classe como quaisquer outros.
Um filho único é uma classe que suporta a criação de apenas um objeto. É como seu computador - há apenas um teclado. Então se você estivesse escrevendo código Delphi que simulou o seu computador, você gostaria apenas um objeto instância para lidar com teclado ler, escrever, e as actividades de controlo.
Artigos sobre Animal aulas são raros, mas existem algumas na Internet. Tenho visto em algumas revistas também. Mas nenhum destes artigos incluem amostras de código para criar uma verdadeira aula únicos.
Pelo "real" Quer dizer que a classe aplica a si própria uma condição de instância, em vez de deixar essa tarefa para o programador. Todos os artigos que tenho visto até agora têm exigido o programador para usar a classe de uma forma especial de fazer valer o Singleton.
Neste artigo você vai ver como criar uma boa coisa única classe que inclui uma lógica de fazer valer a regra de instância.
Nota:A abordagem convencional, em que a regra é uma instância manteve explicitamente pelo programador, não é sem mérito. Real únicos ramos como aquele que eu aqui presentes efetivamente esconder os detalhes e sensibilização do filho único padrão a partir do programador. O programador é aliviado da tarefa de fazer respeitar o padrão - que é bom - mas o programador pode também ser desconhecendo a natureza especial da classe, o que é ruim. Se você não sabe que os únicos class é uma classe, em seguida, todos os tipos de erros podem surgir. Você foi avisado!
Escrever o código
Nosso objetivo é escrever uma classe que pode ser usada como este:
| procedimento de ensaio; var S1, S2: TSingleton; começo s1: = TSingleton.Create; s2: = TSingleton.Create; / / Faz alguma coisa com S1 e S2 aqui s2.Free; s1.Free; final; |
(Eu esqueci de contar os blocos try ... finalmente e outras salvaguardas para a simplicidade do amor.)
O objetivo é fazer o TSingleton classe comportarem de forma a que ambas as S1 e S2 referem-se ao mesmo objeto. Veja o que temos a fazer:
- Instanciar o objeto da primeira vez é chamado Create (s1 quando é criada acima)
- Assegurar que é executado quando um outro Create (s2 acima), o objecto existente é reutilizado, em vez de um outro criado
- Evitar a destruição do objeto quando ele é a última referência que não é destruído (quando for libertado s2)
- Destrói a instância quando a última referência é destruído (quando for libertado s1 acima)
Existe uma maneira de anular a criação e destruição de um novo objeto em Delphi? Aí está certo. No TObject classe (a mãe de todos os objetos) (trocadilhos), existem dois métodos que podemos usar:
| classe função newInstance: TObject; virtual; procedimento FreeInstance; virtual; |
NewInstance é responsável por alocar memória para armazenar uma nova instância da classe, e FreeInstance que é responsável pela liberação de memória quando a classe é através de com ela.
Estes métodos controlar o que acontece quando o objeto é criado e quando o objeto é destruído. Se nós sobrescrever esse código, podemos alterar o comportamento padrão para o trabalho a dizer uma coisa única classe exige. Nada a ela.
Monitoramento de casos é um pouco complicado. Temos que:
- Mantenha o controle de cada instância existente da nossa turma
- Mantenha o controle de quantos ali são referências para este exemplo
- Criar um novo objeto apenas quando existe nenhuma instância
- Destrói o objeto quando a última referência é removida
Para manter o controlo de uma instância existente, iremos usar uma variável global. Na verdade, a variável em última análise, ser declarados dentro da Implementação parte de uma unidade, assim não será um verdadeiro variável global. Mas o alcance deve ser suficiente para acompanhar o Críe todos os convites e gratuito. Iremos chamar a variável Instância, de modo que sabemos o que ele se refere.
Como para manter o rasto de muitas referências como existam, precisamos de uma outra variável. Podemos-la dentro da classe ou torná-lo uma espécie de-globais como Instância. Vou optar por este último caminho, mas fazer o que é você se sentir melhor. I'll Ref_Count nome desta variável.
Temos agora duas variáveis:
| var Instância: TSingleton = nil; Ref_Count: Integer = 0; |
Eu inicializar as variáveis de modo que inicialmente eles não contêm qualquer lixo. Eu sei que o compilador faz isso automaticamente, pelo que esta é apenas uma questão legibilidade.
É preciso declarar a variável TSingleton classe acima do bloco, e se você dar uma olhada no exemplo que você pode fazer download de arquivos no final deste artigo, você verá que eu tenha colocado a declaração na parte de interface o aparelho para que ele é visível fora dela.
Veja aqui a declaração do TSingleton classe:
| tipo TSingleton class = público classe função newInstance: TObject; override; procedimento FreeInstance; override; classe função RefCount: Integer; final; |
Eu adicionei o RefCount função para que possamos ver que realmente funciona, e é muitas vezes útil para ser capaz de ler quantas referências para o objeto existe. Não é exigido, no entanto, de modo que você não tem que adicioná-lo ao seu filho único classes se você não precisar dele.
Ok, agora para a aplicação dos três métodos:
| TSingleton.FreeInstance procedimento; começo Dezembro (Ref_Count); if (Ref_Count = 0) então começo Instância: = nil; / / Destroy privado variáveis aqui herdou FreeInstance; final; final; classe função TSingleton.NewInstance: TObject; começo se (não Assigned (Instância)) então começo Instância: = herdou newInstance; / / Inicializar privado variáveis aqui, como este: / / TSingleton (Resultado). Variável: = Valor; final; Resultado: = Instância Inc (Ref_Count); final; classe função TSingleton.RefCount: Integer; começo Resultado: = Ref_Count; final; |
E isso é tudo!
Quando você chama TSingleton do construtor, uma chamada é colocada para o método newInstance declarado em TObject. Este método aloca memória para armazenar o novo objeto e ele retorna para o construtor. O construtor que usa memória e eventualmente retorna um ponteiro para a memória para o código que chamou o construtor. Este indicador é normalmente armazenado em uma variável, enquanto o objeto estiver em uso.
Tenho ultrapassado o método newInstance assim ele vai alocar a memória só se não houver instância da classe existir. Se existe uma instância existente, a função simplesmente retorna essa instância para o construtor, pelo que irá ser reutilizados.
Se nós chamamos o construtor por três vezes, um objeto é criado apenas na primeira vez. As outras duas chamadas simplesmente reutilizar o primeiro objeto. A referência variável contagem avise-nos que temos três referências à instância única.
Quando o programa solicita o destruidor, uma chamada para FreeInstance é colocado para liberar a memória alocada no construtor. Este método, também, é sobreposto para que o objeto é destruído somente quando a última referência é removida.
Se você pretende usar uma coisa única, em um programa multithreaded, tratar o objeto como faria qualquer variável que você compartilha entre threads. Porque isso é só o que você faz: partilhá-la entre as threads. Então você deve tomar cuidado especial quando alterar os dados.
Simplicidade propriamente dita
Como você pode ver, a criação de uma coisa única classe não exige muito esforço, apenas o direito conhecimentos e algumas linhas de código. O meu código funciona perfeitamente no Delphi 5. A técnica provavelmente irá funcionar bem com versões mais antigas do Delphi, mas eu não tenho testados por isso, não lhe dar garantias.
Antes de eu dar-te a jogar com o arquivo, deixe-me dar-lhe algumas palavras de advertência.
- Não devem descender de uma coisa única classe. A razão para isso é que existe apenas um exemplo e referência contagem variável. Se você derivar duas turmas de TSingleton, apenas um objeto será criado. A outra turma vai reutilizar esse objeto, que será uma instância de uma classe diferente. Não vá por esse caminho!
- Você não pode fazer únicos componentes pela simples razão de propriedade. Um componente é propriedade de um formulário e um componente não pode ser propriedade de vários outros componentes.
- Lembre-se que o construtor eo destruidor denominada get para cada nova referência em que são criados e destruídos. Não inicializar variáveis no construtor privado e não libertá-las no destruidor. Em vez disso, construir esse código na newInstance FreeInstance e os métodos, como mostrado nos comentários.
- A fim de ajustar Ref_Count nos dois métodos em conjunto com o resto do código nesses dois métodos é crítica. Tem a ver com boa criação e destruição quando algo corre mal. Se o seu código inicialização levanta uma exceção, a fim de fazer as coisas como demonstrado acima, certifique-se que a classe é destruída adequadamente. Alterar este código em seu perigo!
O arquivo que você pode fazer o download é apenas uma cópia da unidade que os únicos class declara descrito neste artigo.
Link para o arquivo: CodeCentral entrada 15083.
Eu tenho certeza que você pode encontrar alguns lugares onde uma coisa única classe vem a calhar e agora você tem as ferramentas para criar a sua própria! Se quiser entrar em contato comigo, meu email é lasse@cintra.no
Feliz programação!

Delicious
Digg
Google
Yahoo