2

PHPで簡単なファクトリパターンのデモを作成しようとしています。私のコードがベストプラクティスかどうかはわかりません。コードが重複しているようですが、どうすれば改善できるかわかりません。基本的には、ベーシック、プレミアム、vipの3種類のアカウントを作成したいと思います。お知らせ下さい。どうもありがとう。

抽象クラス

abstract class User {

    function __construct() {
        $this->db= new Database('mysql','localhost','mvcdb','root','');
    }

    abstract function checkUser();

    function showAccountCredit(){
        return $this->credits;
    }
    function getUserName(){
        return $this->username;
    }


}

私は3つの異なるユーザーアカウントタイプを持っています:

ベーシックアカウント

class BasicUser extends User {

    function __construct($username) {
        parent::__construct();
        $this->username=$username;
        $this->credit='10';
        $this->accountType='Basic Account';

        $data=$this->checkUser();

        if(!empty($data)){
            echo 'The username: '.$this->username.' already exists<br>';
            return false;
        }

        $array=array('username'=>$this->username, 'password'=>'password','credit'=> $this->credit,'accountType'=>$this->accountType);
        $this->db->insert('user',$array);

    }


     function checkUser(){

        $array=array(':username'=>$this->username);
        $results=$this->db->select('SELECT * FROM USER WHERE username=:username',$array);
        if(!empty($results)){
        $this->credit=$results[0]['credit'];
        $this->accountType=$results[0]['accountType'];
        }

        return $results;

    }

    function showAccountCredit() {
        echo 'Username: '.$this->username.'<br>';
        echo 'Account Credit: '.$this->credit.'<br>';
        echo 'Account Type: '.$this->accountType;
    }

}

プレミアムアカウント

class PremiumUser extends User {

    function __construct($username) {
        parent::__construct();
        $this->username=$username;
        $this->credit='100';
        $this->accountType='Premium Account';

        $data=$this->checkUser();

        if(!empty($data)){
            echo 'The username: '.$this->username.' already exists<br>';
            return false;
        }

        $array=array('username'=>$this->username, 'password'=>'password','credit'=> $this-                   >credit,'accountType'=>$this->accountType);
        $this->db->insert('user',$array);

    }


     function checkUser(){

        $array=array(':username'=>$this->username);
        $results=$this->db->select('SELECT * FROM USER WHERE username=:username',$array);
        if(!empty($results)){
        $this->credit=$results[0]['credit'];
        $this->accountType=$results[0]['accountType'];
        }

        return $results;

    }

    function showAccountCredit() {
        echo 'Username: '.$this->username.'<br>';
        echo 'Account Credit: '.$this->credit.'<br>';
        echo 'Account Type: '.$this->accountType.'<br>';
    }

}

VIPアカウント:

class VipUser extends User {

    function __construct($username) {
        parent::__construct();
        $this->username=$username;
        $this->credit='1000';
        $this->accountType='VIP Account';

        $data=$this->checkUser();

        if(!empty($data)){
            echo 'The username: '.$this->username.' already exists<br>';
            return false;
        }

        $array=array('username'=>$this->username, 'password'=>'password','credit'=> $this->credit,'accountType'=>$this->accountType);
        $this->db->insert('user',$array);

    }


     function checkUser(){

        $array=array(':username'=>$this->username);
        $results=$this->db->select('SELECT * FROM USER WHERE username=:username',$array);
        if(!empty($results)){
        $this->credit=$results[0]['credit'];
        $this->accountType=$results[0]['accountType'];
        }

        return $results;

    }

    function showAccountCredit() {
        echo 'Username: '.$this->username.'<br>';
        echo 'Account Credit: '.$this->credit.'<br>';
        echo 'Account Type: '.$this->accountType;
    }

}

UserFactoryクラス

class UserFactory {

    static function create($username,$accountType){

        $accountType = strtolower($accountType);

        switch($accountType){
        case 'basic': return new BasicUser($username);
        case 'premium':return new PremiumUser($username);
        case 'vip': return new VipUser($username);
        default :return new BasicUser($username);
        }
    }

index.php

$user1= UserFactory::create('Jerry', 'Vip');
$user1->showAccountCredit();


$user2= UserFactory::create('Bob', 'Basic');
$user2->showAccountCredit();


$user3= UserFactory::create('Betty', 'premium');
$user3->showAccountCredit();
4

1 に答える 1

2

ユーザーの3つの異なる実装を使用する代わりに、「UserType」の3つの異なる実装を検討してください。責任を分離し、オブジェクトを一緒に構成します。これが、戦略と呼ばれる別の動作パターンです。

function showAccountCredit(){
  return $this->type->showAccountCredit();
}

新しいクラス、UserTypeは特別な動作を表します。その後、Userには残りの一般的なものが含まれ、説明した重複(または少なくともそのほとんど)が削減されます。

一方、ファクトリは、dbからオブジェクトをロードするために使用できます。

class Loader{
  private $userTypeFactory;

  public function loadUser($id){
    $userRow = $db->loadRow();
    ...

    $userType = $userTypeFactory->$userRow["type"]();
    return new User($userType);
  }
}

class UserTypeFactory{
  public function vip(){
    return new VipUserType();
  }

  public function premium(){
    return new PremiumUser();
  }
}

さらに一歩進んで、IoCフレームワークを導入することができます。symfony2を見てください。ああ、そしてスイッチを使わないでください、むしろ私がしたように、ポリモーフィズム、ダイナミックコールを使ってください。


編集:

戦略==ラップされた動作。たとえば、プレミアムコンテンツを表示するためのユーザー権限を確認している場合、通常は次のようになります。

class PagesController{
  ...

  public function showPage($id){
    ...
    if ($user->type == "premium" || $user->type == "vip"){
      ...
    }
    else if ($user->type == "credit"){
      $user->credits--;
      updateUser();
    }
    else{
      die("You do not have permissions to see this content...");
    }

    ... //render page
  }
}

そして、「戦略」を使用すると、次のようになります。

class PagesController{
  ...
  public function showPage($id){
    $page = ...;

    $user->pageRequested($page);

    //render page
  }
}

class User{
  private $userType;

  public function pageRequested($page){
    $this->userType->userRequestedPage($user, $page);
  }
}

class VipUserType{
  public function userRequestedPage($user, $page){
    //do nothing
  }
}

class PremiumUserType{
  public function userRequestedPage($user, $page){
    //do nothing
  }
}

class BasicUserType{
  public function userRequestedPage($user, $page){
    throw new Exception("You cant access this page");
  }
}

class CreditUserType{
  public function userRequestedPage($user, $page){
    $user->credit--;
    $user->save();
  }
}

このように、userTypeに関連するすべてのものが分離され、既存の型を壊すリスクなしに新しい型を簡単に追加できます。

ところで:これは単なる古いポリモーフィズムにすぎません。戦略は、ほとんどのパターンと同様に、OOPエッセンシャルのもう1つの輝かしい言葉です。パターンについて考える時間を無駄にしないでください。パターンはインスピレーションに役立ちますが、実際のOOPからより多くの経験を得ることができます。smalltalkをご覧ください-http://www.pharo-project.org/home

于 2012-05-16T21:54:25.573 に答える