diff --git a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
index cc3af53..43f20a1 100644
--- a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
+++ b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
@@ -5,14 +5,9 @@
  */
 
 namespace Drupal\Component\Plugin\Derivative;
-use Drupal\Component\Plugin\PluginTypeInterface;
 
 /**
  * Plugin interface for derivative plugin handling.
- *
- * All methods within this interface are static, so that this interface can be
- * implemented by the plugin class itself, without requiring creating a plugin
- * instance in order to get derivative definitions.
  */
 interface DerivativeInterface {
 
@@ -24,25 +19,19 @@ interface DerivativeInterface {
    *   given base plugin, but derivative ids can be reused across base plugins.
    *   Implementations of
    *   Drupal\Component\Plugin\Discovery\DerivativeDiscoveryInterface combine
-   *   $basePluginId with $derivativeId to construct the derivative's full
+   *   the base plugin id with $derivativeId to construct the derivative's full
    *   plugin id.
    *
    * @param $basePluginDefinition
    *   The definition array of the base plugin from which the derivative plugin
    *   is derived.
    *
-   * @param $basePluginId
-   *   The base plugin identifier.
-   *
-   * @param $pluginType
-   *   The plugin type object.
-   *
    * @return
    *   The full definition array of the derivative plugin, typically a merge of
    *   $basePluginDefinition with extra derivative-specific information. NULL if
    *   the derivative doesn't exist.
    */
-  public static function getDerivativeDefinition($derivativeId, array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType);
+  public function getDerivativeDefinition($derivativeId, array $basePluginDefinition);
 
   /**
    * Returns the definition of all derivatives of a base plugin.
@@ -50,17 +39,11 @@ interface DerivativeInterface {
    * @param $basePluginDefinition
    *   The definition array of the base plugin.
    *
-   * @param $basePluginId
-   *   The base plugin identifier.
-   *
-   * @param $pluginType
-   *   The plugin type object.
-   *
    * @return
    *   An array of full derivative definitions keyed on derivative id.
    *
    * @see getDerivativeDefinition()
    */
-  public static function getDerivativeDefinitions(array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType);
+  public function getDerivativeDefinitions(array $basePluginDefinition);
 
 }
diff --git a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php b/core/lib/Drupal/Component/Plugin/Derivative/StaticDerivativeInterface.php
similarity index 98%
copy from core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
copy to core/lib/Drupal/Component/Plugin/Derivative/StaticDerivativeInterface.php
index cc3af53..172afb6 100644
--- a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
+++ b/core/lib/Drupal/Component/Plugin/Derivative/StaticDerivativeInterface.php
@@ -14,7 +14,7 @@ use Drupal\Component\Plugin\PluginTypeInterface;
  * implemented by the plugin class itself, without requiring creating a plugin
  * instance in order to get derivative definitions.
  */
-interface DerivativeInterface {
+interface StaticDerivativeInterface {
 
   /**
    * Returns the definition of a derivative plugin.
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscovery.php b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscovery.php
index 2bed6dd..f5237e4 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscovery.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscovery.php
@@ -11,6 +11,7 @@ class DerivativeDiscovery implements DerivativeDiscoveryInterface {
 
   protected $pluginType;
   protected $classKey;
+  protected $implementors = array();
 
   public function __construct($pluginType, $classKey) {
     $this->pluginType = $pluginType;
@@ -23,20 +24,20 @@ class DerivativeDiscovery implements DerivativeDiscoveryInterface {
 
   public function getPluginDefinition($pluginId, array $baseDefinition) {
     $basePluginId = $this->getBasePluginId($pluginId);
-    $class = $this->getDerivativeClass($baseDefinition);
+    $implementor = $this->getDerivativeClassOrObject($basePluginId, $baseDefinition);
     if ($pluginId == $basePluginId) {
-      if (isset($class)) {
+      if (isset($implementor)) {
         // Some plugins allow independent existence of the base plugin
         // (derivativeId = NULL), some do not (by returning a NULL definition).
-        $definition = $class::getDerivativeDefinition(NULL, $baseDefinition, $basePluginId, $this->pluginType);
+        $definition = is_object($implementor) ? $implementor->getDerivativeDefinition(NULL, $baseDefinition) : $implementor::getDerivativeDefinition(NULL, $baseDefinition, $basePluginId, $this->pluginType);
       }
       else {
         $definition = $baseDefinition;
       }
     }
-    elseif (isset($class)) {
+    elseif (isset($implementor)) {
       $derivativeId = substr($pluginId, strlen($basePluginId)+1);
-      $definition = $class::getDerivativeDefinition($derivativeId, $baseDefinition, $basePluginId, $this->pluginType);
+      $definition = is_object($implementor) ? $implementor->getDerivativeDefinition($derivativeId, $baseDefinition) : $implementor::getDerivativeDefinition($derivativeId, $baseDefinition, $basePluginId, $this->pluginType);
     }
     else {
       $definition = NULL;
@@ -46,9 +47,9 @@ class DerivativeDiscovery implements DerivativeDiscoveryInterface {
 
   public function getPluginDefinitions($basePluginId, array $baseDefinition) {
     $definitions = array();
-    $class = $this->getDerivativeClass($baseDefinition);
-    if (isset($class)) {
-      $derivativeDefinitions = $class::getDerivativeDefinitions($baseDefinition, $basePluginId, $this->pluginType);
+    $implementor = $this->getDerivativeClassOrObject($basePluginId, $baseDefinition);
+    if (isset($implementor)) {
+      $derivativeDefinitions = is_object($implementor) ? $implementor->getDerivativeDefinitions($baseDefinition) : $implementor::getDerivativeDefinitions($baseDefinition, $basePluginId, $this->pluginType);
       foreach ($derivativeDefinitions as $derivativeId => $definition) {
         $pluginId = strlen($derivativeId) ? "$basePluginId:$derivativeId" : $basePluginId;
         $definitions[$pluginId] = $definition;
@@ -61,20 +62,27 @@ class DerivativeDiscovery implements DerivativeDiscoveryInterface {
   }
 
   /**
-   * Returns the class that implements the DerivativeInterface implementation on behalf of the plugin.
+   * Returns the object that implements DerivativeInterface or class that implements StaticDerivativeInterface on behalf of the plugin.
    *
    * Returns NULL if the plugin doesn't define a value for this class, or if the
    * class doesn't implement the required interface. Not throwing an error for
    * either of these cases allows for flexibility in allowing but not requiring
    * plugin classes to directly handle their own derivative fetching.
    */
-  protected function getDerivativeClass($baseDefinition) {
-    if (isset($baseDefinition[$this->classKey])) {
-      $class = $baseDefinition[$this->classKey];
-      $reflector = new \ReflectionClass($class);
-      if ($reflector->implementsInterface('Drupal\Component\Plugin\Derivative\DerivativeInterface')) {
-        return $class;
+  protected function getDerivativeClassOrObject($basePluginId, $baseDefinition) {
+    if (!isset($this->implementors[$basePluginId])) {
+      $this->implementors[$basePluginId] = FALSE;
+      if (isset($baseDefinition[$this->classKey])) {
+        $class = $baseDefinition[$this->classKey];
+        $reflector = new \ReflectionClass($class);
+        if ($reflector->implementsInterface('Drupal\Component\Plugin\Derivative\DerivativeInterface')) {
+          $this->implementors[$basePluginId] = new $class($basePluginId, $this->pluginType);
+        }
+        elseif ($reflector->implementsInterface('Drupal\Component\Plugin\Derivative\StaticDerivativeInterface')) {
+          $this->implementors[$basePluginId] = $class;
+        }
       }
     }
+    return $this->implementors[$basePluginId] ? $this->implementors[$basePluginId] : NULL;
   }
 }
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php
index 71a63ef..dc899f8 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php
@@ -10,8 +10,8 @@ class DerivativeTest implements DerivativeInterface {
   /**
    * Implements DerivativeInterface::getDerivativeDefinition().
    */
-  public static function getDerivativeDefinition($derivativeId, array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType) {
-    $derivatives = self::getDerivativeDefinitions($basePluginDefinition, $basePluginId, $pluginType);
+  public function getDerivativeDefinition($derivativeId, array $basePluginDefinition) {
+    $derivatives = $this->getDerivativeDefinitions($basePluginDefinition);
     if (isset($derivatives[$derivativeId])) {
       return $derivatives[$derivativeId];
     }
@@ -20,7 +20,7 @@ class DerivativeTest implements DerivativeInterface {
   /**
    * Implements DerivativeInterface::getDerivativeDefinitions().
    */
-  public static function getDerivativeDefinitions(array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType) {
+  public function getDerivativeDefinitions(array $basePluginDefinition) {
     $derivatives = array(
       'test1' => array(
         'string' => 'Test String 1',
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestDerivablePlugin.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestDerivablePlugin.php
index a8973f9..4fa70b6 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestDerivablePlugin.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestDerivablePlugin.php
@@ -8,9 +8,9 @@
 namespace Drupal\plugin_test\Plugin;
 use Drupal\Component\Plugin\PluginAbstract;
 use Drupal\Component\Plugin\PluginTypeInterface;
-use Drupal\Component\Plugin\Derivative\DerivativeInterface;
+use Drupal\Component\Plugin\Derivative\StaticDerivativeInterface;
 
-class TestDerivablePlugin extends PluginAbstract implements DerivativeInterface {
+class TestDerivablePlugin extends PluginAbstract implements StaticDerivativeInterface {
   protected $string;
 
   public function __construct($string) {
@@ -22,7 +22,7 @@ class TestDerivablePlugin extends PluginAbstract implements DerivativeInterface
   }
 
   /**
-   * Implements DerivativeInterface::getDerivativeDefinition().
+   * Implements StaticDerivativeInterface::getDerivativeDefinition().
    */
   public static function getDerivativeDefinition($derivativeId, array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType) {
     $derivatives = self::getDerivativeDefinitions($basePluginDefinition, $basePluginId, $pluginType);
@@ -32,7 +32,7 @@ class TestDerivablePlugin extends PluginAbstract implements DerivativeInterface
   }
 
   /**
-   * Implements DerivativeInterface::getDerivativeDefinitions().
+   * Implements StaticDerivativeInterface::getDerivativeDefinitions().
    */
   public static function getDerivativeDefinitions(array $basePluginDefinition, $basePluginId, PluginTypeInterface $pluginType) {
     return array(
