올바른 디자인 공장입니다. DBI
이 어떻게 처리하는지 살펴보십시오. 어떤 TransferAgent::*
클래스 중 하나를 인스턴스화하는 TransferAgent
클래스로 마무리 할 것입니다. 분명히 아래의 구현보다 많은 오류 검사를 원할 것입니다. 이와 같은 팩토리를 사용하면 코드를 추가하거나 수정할 필요없이 새로운 유형의 전송 에이전트를 추가 할 수 있습니다.
TransferAgent.오후 - 공장 클래스 : A (모의) FTP 클라이언트 구현 : - -
package TransferAgent::Base;
use strict;
use warnings;
use Carp;
sub new {
my ($class, %self) = @_;
$self{_files_transferred} = [];
$self{_bytes_transferred} = 0;
return bless \%self, $class;
}
sub files_sent {
return wantarray ? @{$_[0]->{_files_sent}} :
scalar @{$_[0]->{_files_sent}};
}
sub files_received {
return wantarray ? @{$_[0]->{_files_recv}} :
scalar @{$_[0]->{_files_recv}};
}
sub cwd { return $_[0]->{_cwd} }
sub status { return $_[0]->{_connected} }
sub _subname {
return +(split "::", (caller 1)[3])[-1];
}
sub connect { croak _subname, " is not implemented by ", ref $_[0] }
sub disconnect { croak _subname, " is not implemented by ", ref $_[0] }
sub chdir { croak _subname, " is not implemented by ", ref $_[0] }
sub mode { croak _subname, " is not implemented by ", ref $_[0] }
sub put { croak _subname, " is not implemented by ", ref $_[0] }
sub get { croak _subname, " is not implemented by ", ref $_[0] }
sub list { croak _subname, " is not implemented by ", ref $_[0] }
1;
TransferAgent/FTP.pm
:
package TransferAgent;
use strict;
use warnings;
sub connect {
my ($class, %args) = @_;
require "$class/$args{type}.pm";
my $ta = "${class}::$args{type}"->new(%args);
return $ta->connect;
}
1;
TransferAgent/Base.pm
는 TransferAgent::*
클래스의 기본 기능이 포함되어
package TransferAgent::FTP;
use strict;
use warnings;
use Carp;
use base "TransferAgent::Base";
our %modes = map { $_ => 1 } qw/ascii binary ebcdic/;
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{_mode} = "ascii";
return $self;
}
sub connect {
my $self = shift;
#pretend to connect
$self->{_connected} = 1;
return $self;
}
sub disconnect {
my $self = shift;
#pretend to disconnect
$self->{_connected} = 0;
return $self;
}
sub chdir {
my $self = shift;
#pretend to chdir
$self->{_cwd} = shift;
return $self;
}
sub mode {
my ($self, $mode) = @_;
if (defined $mode) {
croak "'$mode' is not a valid mode"
unless exists $modes{$mode};
#pretend to change mode
$self->{_mode} = $mode;
return $self;
}
#return current mode
return $self->{_mode};
}
sub put {
my ($self, $file) = @_;
#pretend to put file
push @{$self->{_files_sent}}, $file;
return $self;
}
sub get {
my ($self, $file) = @_;
#pretend to get file
push @{$self->{_files_recv}}, $file;
return $self;
}
sub list {
my $self = shift;
#pretend to list remote files
return qw/foo bar baz quux/;
}
1;
script.pl
을 - TransferAgent 사용 방법 :
#!/usr/bin/perl
use strict;
use warnings;
use TransferAgent;
my $ta = TransferAgent->connect(
type => "FTP",
host => "foo",
user => "bar",
password => "baz",
);
print "files to get: ", join(", ", $ta->list), "\n";
for my $file ($ta->list) {
$ta->get($file);
}
print "files gotten: ", join(", ", $ta->files_received), "\n";
$ta->disconnect;
여기에 어떤 일이 벌어지고 있는지에 대한 설명을 추가하는 것이 좋습니다. 그러나 여전히 좋은 대답입니다. –
거짓 값이 유효한 코드 레퍼런스가 아니기 때문에 정의 할 필요가 없습니다. 또한 조회 테이블에서 메소드를 찾을 수없는 경우 경고를 표시해야합니다. 대안은 모든 메소드를 클래스에 넣고'can '을 사용하는 것입니다. –
@Sinan Ünür- $ trans_type eq "fronobulax?" 다른 말로하면, 그는 기대하지 않았거나 예상하지 못한 유형 이었습니까? – xcramps