정적 방법 코드 냄새를 제거하기위한 리팩토링
-
23-08-2019 - |
문제
작성해야 할 각 도메인 객체의 현재 기본 구조가 있습니다.
class Model_Company extends LP_Model
{
protected static $_gatewayName = 'Model_Table_Company';
protected static $_gateway;
protected static $_class;
public static function init()
{
if(self::$_gateway == null)
{
self::$_gateway = new self::$_gatewayName();
self::$_class = get_class();
}
}
public static function get()
{
self::init();
$param = func_get_arg(0);
if($param instanceof Zend_Db_Table_Row_Abstract)
{
$row = $param;
}
elseif(is_numeric($param))
{
$row = self::$_gateway->find($param)->current();
}
return new self::$_class($row);
}
public static function getCollection()
{
self::init();
$param = func_get_arg(0);
if($param instanceof Zend_Db_Table_Rowset_Abstract)
{
$rowset = $param;
}
elseif(!$param)
{
$rowset = self::$_gateway->fetchAll();
}
$array = array ();
foreach ($rowset as $row)
{
$array[] = new self::$_class($row);
}
return $array;
}
}
처음에는 정적 메소드를 부모 LP_MODEL 클래스로 리팩터링하려고 시도하여 PHP 세계에서 "늦은 정적 바인딩"이 무엇을 의미하는지 최종적으로 배우기 위해 노력했습니다.
내가 만든 모든 도메인 객체에서 동일한 세 가지 함수를 재개 할 필요가 없도록이 코드를 리팩터링하는 방법에 대한 제안이 있는지 궁금합니다.
해결책
이건 어때:
<?php
abstract class Model_Abstract
{
protected $_gatewayName = null;
protected $_gateway = null;
protected function _init()
{
$this->_gateway = new $this->_gatewayName();
}
protected function __construct($row = null)
{
$this->_init();
if ($row) {
$this->_data = $row;
}
}
public static function getAbstract($class, $param)
{
$model = new $class();
if($param instanceof Zend_Db_Table_Row_Abstract)
{
$row = $param;
}
elseif(is_numeric($param))
{
$row = $model->_gateway->find($param)->current();
}
return new $class($row);
}
public static function getAbstractCollection($class, $param = null)
{
$model = new $class();
if($param instanceof Zend_Db_Table_Rowset_Abstract)
{
$rowset = $param;
}
elseif($param === null)
{
$rowset = $model->_gateway->fetchAll();
}
$array = array ();
foreach ($rowset as $row)
{
$array[] = new $class($row);
}
return $array;
}
abstract public static function get($param);
abstract public static function getCollection($param = null);
}
class Model_Company extends Model_Abstract
{
protected $_gatewayName = 'Model_Table_Company';
public static function get($param) {
return self::getAbstract(__CLASS__, $param);
}
public static function getCollection($param = null) {
return self::getAbstractCollection(__CLASS__, $param);
}
}
class Model_Table_Company extends Zend_Db_Table_Abstract
{
protected $_name = 'company';
}
$model = Model_Company::get(1);
print "Got an object of type ".get_class($model)."\n";
$models = Model_Company::getCollection();
print "Got ".count($models)." objects of type ".get_class($models[0])."\n";
?>
불행히도 기능을 쉽게 호출 할 수 있도록하려면 복제해야합니다. get()
그리고 getCollection()
각 서브 클래스에서. 다른 옵션은 부모 클래스에서 함수를 호출하는 것입니다.
$model = Model_Abstract::getAbstract('Model_Company', 1);
print "Got an object of type ".get_class($model)."\n";
$models = Model_Abstract::getAbstractCollection('Model_Company');
print "Got ".count($models)." objects of type ".get_class($models[0])."\n";
해당 경로로 이동하려면 기본 클래스 및 기능 이름의 이름을 바꿀 수 있습니다. 그러나 요점은 그 것입니다 한 곳이나 다른 곳에서 자식 수업을 지정해야합니다.: 첫 번째 예제에서와 같이 아동 클래스에서 보일러 플레이트 기능을 만들거나 두 번째 예에서와 같이 문자열의 클래스를 이름으로 지정하십시오.
제휴하지 않습니다 StackOverflow