我试图在编程中尽可能地遵循DRY原则。最近,我一直在学习OOP中的设计模式,最后又重复了一遍。
我创建了一个Repository模式以及一个Factory模式和Gateway模式来处理我的持久性。我在应用程序中使用数据库,但这没关系,因为如果我愿意,我应该能够换出网关并切换到另一种持久性。
我最终为自己创建的问题是,我为拥有的表数创建了相同的对象。例如,这些将是我需要处理表的对象comments
。
class Comment extends Model {
protected $id;
protected $author;
protected $text;
protected $date;
}
class CommentFactory implements iFactory {
public function createFrom(array $data) {
return new Comment($data);
}
}
class CommentGateway implements iGateway {
protected $db;
public function __construct(\Database $db) {
$this->db = $db;
}
public function persist($data) {
if(isset($data['id'])) {
$sql = 'UPDATE comments SET author = ?, text = ?, date = ? WHERE id = ?';
$this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date'], $data['id']);
} else {
$sql = 'INSERT INTO comments (author, text, date) VALUES (?, ?, ?)';
$this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date']);
}
}
public function retrieve($id) {
$sql = 'SELECT * FROM comments WHERE id = ?';
return $this->db->prepare($sql)->execute($id)->fetch();
}
public function delete($id) {
$sql = 'DELETE FROM comments WHERE id = ?';
return $this->db->prepare($sql)->execute($id)->fetch();
}
}
class CommentRepository {
protected $gateway;
protected $factory;
public function __construct(iFactory $f, iGateway $g) {
$this->gateway = $g;
$this->factory = $f;
}
public function get($id) {
$data = $this->gateway->retrieve($id);
return $this->factory->createFrom($data);
}
public function add(Comment $comment) {
$data = $comment->toArray();
return $this->gateway->persist($data);
}
}
然后我的控制器看起来像
class Comment {
public function view($id) {
$gateway = new CommentGateway(Database::connection());
$factory = new CommentFactory();
$repo = new CommentRepository($factory, $gateway);
return Response::view('comment/view', $repo->get($id));
}
}
所以我以为我正确地使用了设计模式并保持了良好的实践,但是这件事的问题是,当我添加一个新表时,我必须使用其他名称来创建相同的类。这使我怀疑我做错了什么。
我想到了一个解决方案,其中我没有接口,而是有抽象类,这些抽象类使用类名找出需要操作的表,但这似乎不是正确的选择,如果我决定切换到文件存储或没有表的memcache。
我是在正确地解决这个问题,还是应该以不同的视角看待?