Anyway the code that you wrote (just checking if I understood everything right) allows me to create more instances of DBIx::Handy, but only one DB connection?
If you want that, then $dbh is just the equivalent of a static field, shared between all DBIx::Handy objects (in a process). That may be fine, but to be a classic Singleton get_instance should conditionally create and return the sole instance of its class.
The difference is more obvious in Object Oriented languages where new is more than just a naming convention. See SingletonPattern.
The nice thing about design patterns is that they should be modified to suit your needs. In your case, I would be inclinded to have a class that manages the configuration and singleton-ness of your database handle(s). That way you avoid passing around existing objects or creating new ones that just wrap static fields. By encapsulating each database connection in a class, you can skip the need for memoization and localize changes. Bonus!
package DBIx::Handy::Singleton;
our @ISA = ('DBIx::Handy');
my %instances = ();
sub new{
die "ack! Cant call new on Singleton class '$_[0]'!\n";
}
sub get_instance
{
my $class = ref $_[0] || $_[0];
unless($instances{$class}){
my $dbh = bless DBIx::Handy->new( $class->configure() ), $clas
+s;
$dbh->connect();
# ...etc
$instances{$class} = $dbh;
}
return $instances{$class};
}
sub configure{
die "Unimplemented abstract method 'configure' in '$_[0]'\n";
}
package MyApp::Foo;
our @ISA = ('DBIx::Handy::Singleton');
sub configure{
return (driver => ..., database => ..., ...);
}
package MyApp::Bar;
our @ISA = ('DBIx::Handy::Singleton');
sub configure{
return (driver => ..., database => ..., ...);
}
As for the mod_perl/threading issues, I dont know enough about either to comment fully, other than to say that usually access
to get_instance would be limited to one thread to avoid race conditions while checking the singleton exists. Check CPAN,
a quick search brought up Apache::Singleton...
time was, I could move my arms like a bird and...