hkl: Muster - die einsame [KB]ruecke

Beitrag lesen

( singleton bridge )
Hallo !

Unter Perl gibt es ja die Moeglichkeit auf Funktoinen in einem Modul mittels <PAKETNAME>::<Fumktionsname> zuzugreifen. Wenn man das Paket aber objektorientiert nutzen will, ist das ja nicht ganz unproblmatisch, da es sein koennte dass der Konstruktor noch gar nicht gerufen wurde.

Das kann wie hier gezeigt mittels einer Praeambel

sub tmpdir {

BEGIN Praeambel

my $self = shift;
      $self = __PACKAGE__->instance
          unless ref $self eq __PACKAGE__;

END Praeambel

#...
}

im Funktionskoerper abgefangen werden, aber es laesst sich vielleicht auch semantisch unterdruecken* :

Hab mal ein Singleton entworfen das das Problem loesen soll:

modules/Log.pm

use strict;
package Log::LogImpl;

if ( defined __PACKAGE__  and __PACKAGE__ eq 'Log' )
{
 sub log {
  my $class = shift;
  my $msg = shift;
  print scalar(localtime(time)) . " " . "$msg\n";
 }
}

package Log;

my $_self = undef;

BEGIN

{

eben nicht hier konstruiert !

}

my %attrs = ( foo => 'bar'
);

returns singleton reference

sub _getInstance {
 $_self ||= do {
  # Dies vermeidet einen Aufruf
                # wie Log::log
                @Log::ISA = 'Log::LogImpl';
  bless { %attrs }, 'Log';
 };
}

END

{

}

1;

EOF Log.pm

Wenn jetzt ein Client versucht die Methode mittels "Log::log" aufzurufen, wuerde das nicht klappen :

#! /usr/bin/perl -w -I ./modules

LogClient.pl

tests encapsulation cherence

use strict;
use Log;
my $log = Log::_getInstance()
 or die 'Could not get instance for log' . "\n" ;
eval ("Log::log('Logged in class scope...')")
 and die '...by accident ! Terminating' . "\n"
  or print 'Method "log" not in class scope...' . "\n";

$log->log('Logged correctly')
 and print '...but in object scope, as intended !' . "\n" ;

EOF LogClient.pl

Das Ganze ist eigentlich ein degeneriertes Brueckenmuster; degeneriert, da hier eben grade nicht die Implementierung aggregiert sondern inkludiert wird, was dem Konzept loser Koppelung, das die "GoF" thematisiert, wiederspricht.
Ausserdem handelt es sich um keine Implemetierungs-"Klasse" (kein bless) sondern um ein einfaches Paket.

Trotzdem find ich das recht praktisch.

Habe noch nicht soviel Erfahrung mit Perl - hier einige Fragen an Euch Wizards:

Ist das Eurer Meinung nach

  • eval('undef'); # ;-)
  • (void*) NULL; // Denn Perl ist nun mal kein C++
  • Voelliger Mist
  • Verwirrend fuer den Nutzer
  • Kalter Kaffee # "Das mach ich doch seit Beginn der Epoche besser..."
  • vielleicht doch irgendwie brauchbar
  • ...

?

Ueber Feedback wuerde ich mich sehr freuen

Danke fuer's Lesen

Gruss && schones Wochenende

Holger

*) Ich weiss dass meine Loesung einen Compiler-Fehler provoziert, die Praeambel-Loesung nicht. Genau damit will ich aber eine Aufrufkonverntion erzwingen.