diff --git a/Model/Filter/AbstractListFilter.php b/Model/Filter/AbstractListFilter.php
new file mode 100644
index 0000000000000000000000000000000000000000..69c91f75fb7bd87a39035848e426a6f440d5b828
--- /dev/null
+++ b/Model/Filter/AbstractListFilter.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model\Filter;
+
+use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
+use ReflectionClass;
+
+/**
+ * Description of AbstractListFilter
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+abstract class AbstractListFilter implements ClassFilterInterface
+{
+    /**
+     * @var string[]
+     */
+    private $allowed = [];
+
+    /**
+     * @var boolena
+     */
+    private $notFound;
+
+    public function __construct(array $allowed, $notFound = false)
+    {
+        $this->allowed = array_map([$this, 'normalize'], $allowed);
+        $this->notFound = $notFound;
+    }
+
+    public function accept(ReflectionClass $class)
+    {
+        $tested = $this->normalize($this->extract($class));
+        foreach ($this->allowed as $reference) {
+            if ($this->matches($tested, $reference)) {
+                return !$this->notFound;
+            }
+        }
+        return $this->notFound;
+    }
+
+    /**
+     * @param string $value
+     * @return string
+     */
+    abstract protected function normalize($value);
+
+    /**
+     * @param ReflectionClass $class
+     * @return string
+     */
+    abstract protected function extract(ReflectionClass $class);
+
+    /**
+     * @param string $value
+     * @return bool
+     */
+    abstract protected function matches($tested, $reference);
+}
diff --git a/Model/Filter/ClassFilter.php b/Model/Filter/ClassFilter.php
index 0ace595c8e2658ea3addbcbca520626372e3c99b..2dc8f03f28823dcebd85844e5c92c98a1f0b26a9 100644
--- a/Model/Filter/ClassFilter.php
+++ b/Model/Filter/ClassFilter.php
@@ -8,7 +8,6 @@
 
 namespace Irstea\PlantUmlBundle\Model\Filter;
 
-use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
 use ReflectionClass;
 
 /**
@@ -16,35 +15,20 @@ use ReflectionClass;
  *
  * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
  */
-class ClassFilter implements ClassFilterInterface
+class ClassFilter extends AbstractListFilter
 {
-    /**
-     * @var string[]
-     */
-    private $classes = [];
-
-    /**
-     * @var boolena
-     */
-    private $notFound;
+    protected function extract(ReflectionClass $class)
+    {
+        return $class->getName();
+    }
 
-    public function __construct(array $classes, $notFound = false)
+    protected function matches($tested, $reference)
     {
-        $this->classes = array_map(
-            function ($class) {
-                return trim($class, '\\');
-            },
-            $classes
-        );
-        $this->notFound = $notFound;
+        return $tested === $reference;
     }
 
-    public function accept(ReflectionClass $class)
+    protected function normalize($className)
     {
-        $className = $class->getName();
-        if (in_array($className, $this->classes)) {
-            return !$this->notFound;
-        }
-        return $this->notFound;
+         return trim($className, '\\');
     }
 }
diff --git a/Model/Filter/DirectoryFilter.php b/Model/Filter/DirectoryFilter.php
index 85fa8cf56db664875228e7a33472897fcb5e6263..4380fcceac066c4fced9d1d18240bbdd45e1a801 100644
--- a/Model/Filter/DirectoryFilter.php
+++ b/Model/Filter/DirectoryFilter.php
@@ -8,7 +8,6 @@
 
 namespace Irstea\PlantUmlBundle\Model\Filter;
 
-use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
 use ReflectionClass;
 
 /**
@@ -16,37 +15,20 @@ use ReflectionClass;
  *
  * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
  */
-class DirectoryFilter implements ClassFilterInterface
+class DirectoryFilter extends AbstractListFilter
 {
-    /**
-     * @var string[]
-     */
-    private $paths = [];
-
-    /**
-     * @var boolean
-     */
-    private $notFound;
+    protected function extract(ReflectionClass $class)
+    {
+        return dirname($class->getFileName());
+    }
 
-    public function __construct(array $paths, $notFound = false)
+    protected function matches($tested, $reference)
     {
-        $this->paths = array_map(
-            function ($path) {
-                return rtrim(strtr($path, '/\\', DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
-            },
-            $paths
-        );
-        $this->notFound = $notFound;
+        return strpos($tested, $reference) === 0;
     }
 
-    public function accept(ReflectionClass $class)
+    protected function normalize($path)
     {
-        $filepath = dirname($class->getFileName());
-        foreach($this->paths as $path) {
-            if (strpos($filepath, $path) === 0) {
-                return !$this->notFound;
-            }
-        }
-        return $this->notFound;
+         return rtrim(strtr($path, '/\\', DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
     }
 }
diff --git a/Model/Filter/NamespaceFilter.php b/Model/Filter/NamespaceFilter.php
index 4b01aa2f1eced69ea3717851e52ef3a4db4faa19..5226caaa5059c945a3c83fad769231c95fa80720 100644
--- a/Model/Filter/NamespaceFilter.php
+++ b/Model/Filter/NamespaceFilter.php
@@ -8,7 +8,6 @@
 
 namespace Irstea\PlantUmlBundle\Model\Filter;
 
-use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
 use ReflectionClass;
 
 /**
@@ -16,37 +15,20 @@ use ReflectionClass;
  *
  * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
  */
-class NamespaceFilter implements ClassFilterInterface
+class NamespaceFilter extends AbstractListFilter
 {
-    /**
-     * @var string[]
-     */
-    private $namespaces = [];
-
-    /**
-     * @var boolena
-     */
-    private $notFound;
+    protected function extract(ReflectionClass $class)
+    {
+        return $class->getNamespaceName();
+    }
 
-    public function __construct(array $namespaces, $notFound = false)
+    protected function matches($tested, $reference)
     {
-        $this->namespaces = array_map(
-            function ($namespace) {
-                return trim($namespace, '\\').'\\';
-            },
-            $namespaces
-        );
-        $this->notFound = $notFound;
+        return strpos($tested, $reference) === 0;
     }
 
-    public function accept(ReflectionClass $class)
+    protected function normalize($namespace)
     {
-        $className = $class->getNamespaceName().'\\';
-        foreach($this->namespaces as $namespace) {
-            if (strpos($className, $namespace) === 0) {
-                return !$this->notFound;
-            }
-        }
-        return $this->notFound;
+         return trim($namespace, '\\').'\\';
     }
 }