package Thing; # default constructor for all "Thing"s sub new { my ($class,%options) = @_; my $self = { %options }; return bless $self, ref($class) || $class; } # abstract method stub sub do { my $self = shift; die ref($self) || $self . " did not implement do()\n"; } package Thing::A sub do { my $self = shift; print "This is " . ref($self) || $self . "\n"; } package Thing::B sub do { my $self = shift; print "I'm a really cool " . ref($self) || $self . "\n"; } package ThingFactory; my %dispatch = ( 'A' => 'Thing::A', 'B' => 'Thing::B', '_default' => 'Thing::A', ); sub createThing { my ($class,%options) = @_; unless( exists($options{'thing'}) && $options{'thing'} ) { return $dispatch{'_default'}->new(%options); } elsif( !exists($dispatch{$options{'thing'}}) ) { return $dispatch{'_default'}->new(%options); } else { return $dispatch{$options{'thing'}}->new(%options); } } package main; my $thing = ThingFactory->createThing('thing' => 'A'); $thing->do();