0

我的数据库中有名为帖子的表。每个帖子都有名为social_network的字段

当我在我的代码中将所有帖子放入数组时,我需要根据它的social_network字段为每个帖子创建实例。

现在我为此使用 switch 语句,但我不喜欢它,因为它不灵活。

$posts = DataBase::getPosts(); // pseudocode
foreach($posts as $post) {
  switch($post->getSocialNetwork()){
    case 'Facebook':
      $social = new FacebookPost($post->getId());
      break;
    case 'Twitter':
      $social = new TwitterPost($post->getId());
      break;        
    // .... other social networks
  }
}
4

3 回答 3

7

将接口添加到定义了相同基本必要方法的类 FacebookPost 和 TwitterPost(例如 SocialPostInterface)getId()postToNetwork()然后您可以根据需要添加任意数量的新社交网络,而无需更改这段代码。他们只需要实现接口

然后体验多态的威力:

foreach ($posts as $post) {
    $className = $post->getSocialNetwork() . 'Post';
    // lets check if such class exists
    if (!class_exists($className, false /* do not attempt autoload */)) {
        throw new Exception("Unknown social network post class $className");
    }
    $social = new $className($post->getId());
    $social->doSomeStuffThatTheInterfaceHasDeclared();
}
于 2012-04-09T14:26:54.347 回答
4

我不认为你可以避免这种代码。但是您可能希望将其移至抽象工厂,因此您不必在控制器中查看它。

$posts = DataBase::getPosts(); // pseudocode
foreach($posts as $post) {
    $social = SocialFactory::post($post);
  }
}
于 2012-04-09T14:30:19.277 回答
1
$socialClass = $post->getSocialNetwork() . 'Post';
$social = new $socialClass($post->getId());

您可以从包含其名称的字符串中创建一个新对象。

于 2012-04-09T14:29:50.963 回答