dongxinyue2817 2018-07-28 18:32
浏览 41

在不改变源代码的情况下扩展程序。 SOLID PHP OOP

Let's say we have few elements:

1) Simple PHP Class

<?php 
  class page {
    function display() {
      // Display widgets implementing widget interface
    }
 }
?>

2) Interface for Widget Classes

<?php 
  interface Widget {
    function print();
  }
?>

3) And few classes implementing the Widget interface

<?php
  class Poll implements Widget {
    function print() {
      echo "I'm a poll";
    }
  }

 class Form implements Widget {
   function print() {
     echo "I'm a form";
   }
 } 
?>

What is the right way taking in mind SOLID PHP OOP logic to automatically run print() function in all classes implementing Widget interface? Let's assume all the files are already included.

Basically, whenever new class implementing Widget is created, it's response should be printed out in a page.

Maybe all my logic behind this is wrong?

  • 写回答

3条回答 默认 最新

  • dongtuji0992 2018-07-29 09:06
    关注

    The only way I could think of without using any config or database is to get all declared classes and check the ones that implement the Widget interface:

    This is the modified Page class

    class Page {
    
        public $widgets = [];
    
        public function addWidget(Widget $widget)
        {
            $this->widgets[] = $widget;
        }
    
        public function display()
        {
            // Now you have an array of Widgets you can loop through them
            // And run print()
            foreach ($this->widgets as $widget) {
                $widget->print();
            }
        }
    }
    

    And then we can get all classes (that are loaded) that implement the Widget interface:

    $widgets = array_filter(
        get_declared_classes(),
        function ($className) {
            return in_array('Widget', class_implements($className));
        }
    );
    

    And then we pass them to Page:

    $page = new Page();
    foreach ($widgets as $item) {
        $widget = new $item;
        $page->addWidget($widget);
    }
    
    // Now Page has all Widgets we can call display()
    $page->display();
    

    But be aware that get_declared_classes() will return a lot of classes (160 in my PC), so we are looping through them all and checking if each one implements the Widget interface.

    Now whenever you have a class that implements the Widget interface it will be used by Page. To be honest I don't know if there is a better way so it might be worth it to wait for other answers.

    评论

报告相同问题?