php – 多级继承替换
我想编写一个模块(特定于框架),它将包装和扩展Facebook
PHP-sdk(
https://github.com/facebook/php-sdk/).我的问题是 – 如何以一种很好的方式组织课程.
所以深入细节 – Facebook PHP-sdk包含两个类: > BaseFacebook – 包含sdk所有内容的抽象类 现在我有一些功能要添加: > Facebook类替换,与框架会话类集成 我知道有些事情出了问题,因为我有太多的遗传,看起来不太正常.将所有内容包含在一个“复杂扩展”类中似乎也太过分了.我想我应该很少工作togheter类 – 但我遇到的问题如下:如果缓存类没有真正扩展并覆盖BaseFacebook :: api()方法 – 简写和身份验证类将无法使用缓存. 也许某种模式会在这里?您将如何组织这些类及其依赖项? 编辑04.07.2012 与主题相关的代码位: 这是Facebook PHP-sdk的基类: abstract class BaseFacebook { // ... some methods public function api(/* polymorphic */) { // ... method,that makes api calls } public function getUser() { // ... tries to get user id from session } // ... other methods abstract protected function setPersistentData($key,$value); abstract protected function getPersistentData($key,$default = false); // ... few more abstract methods } Normaly Facebook类扩展了它,并且对这些抽象方法提出了要求.我用我的替代品替换它 – Facebook_Session类: class Facebook_Session extends BaseFacebook { protected function setPersistentData($key,$value) { // ... method body } protected function getPersistentData($key,$default = false) { // ... method body } // ... implementation of other abstract functions from BaseFacebook } 好的,然后我用速记方法和配置变量扩展它: class Facebook_Custom extends Facebook_Session { public function __construct() { // ... call parent's constructor with parameters from framework config } public function api_batch() { // ... a wrapper for parent's api() method return $this->api('/?batch=' . json_encode($calls),'POST'); } public function redirect_to_auth_dialog() { // method body } // ... more methods like this,for common queries / authorization } 我不确定,如果这对单个类来说不是太多(授权/速记方法/配置).然后是另一个扩展层 – 缓存: class Facebook_Cache extends Facebook_Custom { public function api() { $cache_file_identifier = $this->getUser(); if(/* cache_file_identifier is not null and found a valid file with cached query result */) { // return the result } else { try { // call Facebook_Custom::api,cache and return the result } catch(FacebookApiException $e) { // if Access Token is expired force refreshing it parent::redirect_to_auth_dialog(); } } } // .. some other stuff related to caching } 现在这很有效. Facebook_Cache的新实例为我提供了所有功能. Facebook_Custom的速记方法使用缓存,因为Facebook_Cache覆盖了api()方法.但这里有什么困扰我: >我认为这是太多的继承. 再说一遍,这是有效的,但我只是想要以更清洁,更智能的方式进行模式/方式.
辅助功能(如缓存)通常作为装饰器实现(我在另一条评论中已经提到过).装饰器最适合接口,所以我首先创建一个:
interface FacebookService { public function api(); public function getUser(); } 保持简单,不要在外部添加任何不需要的东西(例如setPersistentData).然后在新界面中包装现有的BaseFacebook类: class FacebookAdapter implements FacebookService { private $fb; function __construct(BaseFacebook $fb) { $this->fb = $fb; } public function api() { // retain variable arguments return call_user_func_array(array($fb,'api'),func_get_args()); } public function getUser() { return $fb->getUser(); } } 现在编写缓存装饰器很容易: class CachingFacebookService implements FacebookService { private $fb; function __construct(FacebookService $fb) { $this->fb = $fb; } public function api() { // put caching logic here and maybe call $fb->api } public function getUser() { return $fb->getUser(); } } 然后: $baseFb = new Facebook_Session(); $fb = new FacebookAdapter($baseFb); $cachingFb = new CachingFacebookService($fb); $fb和$cachingFb都暴露了相同的FacebookService接口 – 因此您可以选择是否要缓存,其余代码根本不会更改. 至于你的Facebook_Custom类,它现在只是一堆辅助方法;您应该将其分解为一个或多个包装FacebookService并提供特定功能的独立类.一些示例用例: $x = new FacebookAuthWrapper($fb); $x->redirect_to_auth_dialog(); $x = new FacebookBatchWrapper($fb); $x->api_batch(...); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |