简单的工厂模式演示


Simple Factory Pattern Demo

我正在尝试在PHP中创建一个简单的工厂模式演示。我不确定我的代码是否是最佳实践。似乎我有一些重复的代码,但我不确定如何改进它。基本上,我想创建3种类型的帐户(基本,高级和VIP(。请指教。多谢。

抽象类

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>';
    }
}

贵宾账户:

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;
    }
}

用户工厂类

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);
        }
    }

索引.php

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

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

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

与其有 3 种不同的用户实现,不如考虑 3 种不同的 "UserType" 实现。分离职责并组合对象。这是另一种行动模式,称为战略

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

新类,UserType代表特殊行为,然后用户将包含其余的通用内容,减少您描述的重复(或至少大部分(

另一方面,工厂可用于从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要点的另一个闪亮词,就像大多数模式一样。不要浪费时间思考模式,它们对灵感有好处,但是你会从真正的OOP中获得更多经验,看看smalltalk - http://www.pharo-project.org/home