Jos*_*ith 5 php oop refactoring
我有一个类如下:
class DreamsImagesStore
{
public $table = 'dreams_images';
public function insertNewDreamImage($dream_id, $pid)
{
try {
$values = array($dream_id, $pid);
$sth = $this->dbh->prepare("INSERT INTO {$this->table}
(dream_id, pid)
VALUES (?, ?)");
if($sth->execute($values)) {
return true;
}
} catch(PDOException $e) {
$this->errorLogger($e);
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
我将要实施一项名为InterestsImagesStore新的类,其中这些类之间的唯一区别将是价值$table,$dream_id将$interest_id和dream_id在SQL会interest_id.
我知道有更好的方法可以做到这一点,我将在未来实现类似的类,这些类有很小的差异.
为了避免重复和提高可维护性,重构代码的最佳面向对象方法是什么?
Ric*_*ook 11
创建ImagesStore基类:
class ImagesStore
{
// See comments about accessors below.
private $table;
private $id_column;
public function insertImage($id, $pid) {
try {
$values = array($id, $pid);
$table = $this->getTable();
$id_column = $this->getIdColumn();
$sth = $this->dbh->prepare("INSERT INTO {$table} ($id_column, pid) VALUES (?, ?)");
if ($sth->execute($values)) {
return true;
}
}
catch (PDOException $e) {
$this->errorLogger($e);
}
}
protected function __construct($table, $id_column) {
$this->table = $table;
$this->id_column = $id_column;
}
// These accessors are only required if derived classes need access
// to $table and $id_column. Declaring the fields "private" and providing
// "protected" getters like this prevents the derived classes from
// modifying these values which might be a desirable property of these
// fields.
protected function getTable() {return $this->table;}
protected function getIdColumn() {return $this->id_column;}
// More implementation here...
// Initialize $dbh to something etc.
// Provide "errorLogger" method etc.
}
Run Code Online (Sandbox Code Playgroud)
并创建DreamsImagesStore和InterestsImagesStore专业化:
class DreamsImagesStore extends ImagesStore {
public function __construct() {
parent::__construct('dreams_images', 'dream_id');
}
}
class InterestsImagesStore extends ImagesStore {
public function __construct() {
parent::__construct('interests_images', 'interest_id');
}
}
Run Code Online (Sandbox Code Playgroud)
原始方法insertNewDreamImage可以重命名为,insertImage因为它比原始名称更普遍.
请注意,如果要阻止对其进行直接实例化,ImagesStore也可以声明abstract.
可以采用的另一种方法是不打扰从中派生类ImagesStore,只需通过生成__construct方法public并按如下方式调用它来直接实例化它:
$dreamsImagesStore = new ImagesStore("dreams_images", "dream_id");
Run Code Online (Sandbox Code Playgroud)
另一种方法也可能是实现静态工厂方法ImagesStore.