Rather than creating complex inheritance trees, consider creating a generic serialization interface for your shopping cart and put the serializer in your cart object.
# Create the cart
my $cart = new Cart( type => 'DBI', id => $foo );
print "Cart's current total is: ", $cart->total_cost();
# Be sure we don't sell anything inappropriate!
foreach my $item ( $cart->list_items ) {
if ( $item->type eq 'adult' && $user->age < 18 ) {
$cart->remove_item( $item );
}
}
$cart->save;
print "Cart's new total is: ", $cart->total_cost();
Using something like (ahem!) Class::Factory, the initialization and some of the cart code might look like:
package Cart;
# 'id', 'serializer' are accessor/mutator functions
# like those created by Class::Accessor
sub new {
my ( $class, %params ) = @_;
my $self = bless( {}, $class );
$self->id( $params{id} );
my $serializer = Cart::Serializer->new( $params{type}, $id );
$self->serializer( $serializer );
return $self;
}
sub list_items { ... }
sub add_item { ... }
sub remove_item { ... }
sub total_cost { ... }
sub save {
my ( $self ) = @_;
my $serializer = $self->serializer;
$serializer->save( $self );
}
package Cart::Serializer;
use base qw( Class::Factory );
my %TYPES = ( DBI => 'Cart::Serializer::DBI',
LDAP => 'Cart::Serializer::LDAP',
File => 'Cart::Serializer::File' );
sub get_factory_map { return \%TYPES };
sub save { die "Implement in subclass!" }
package Cart::Serializer::DBI;
sub init {
my ( $self, $id ) = @_;
# ... do DBI fetch ...
}
sub save {
my ( $self, $cart ) = @_;
# ... save to DBI table ...
}
package Cart::Serializer::LDAP;
sub init {
my ( $self, $id ) = @_;
# ... do LDAP fetch ...
}
sub save {
my ( $self, $cart ) = @_;
# ... save to LDAP tree ...
}
package Cart::Serializer::File;
sub init {
my ( $self, $id ) = @_;
# ... read from filesystem
}
sub save {
my ( $self, $cart ) = @_;
# ... save to filesystem ...
}
Hopefully this makes some sense. I have on my wall three of the core ideas from the Gang of Four book, and the second one is Favor composition over inheritance, which I try to follow whenever possible. "Think about loose coupling" and all that :-)
Chris
M-x auto-bs-mode