diff --git a/Command/GenerateCommand.php b/Command/GenerateCommand.php
index dbc497a21c8e177682876c2fc48630643af1b2a5..d2748355f0ba6d29b44314eb458def70765cdd2b 100644
--- a/Command/GenerateCommand.php
+++ b/Command/GenerateCommand.php
@@ -10,6 +10,10 @@ use Doctrine\ORM\EntityManagerInterface;
 use Irstea\PlantUmlBundle\Doctrine\AssociationDecorator;
 use Irstea\PlantUmlBundle\Doctrine\DoctrineNamespace;
 use Irstea\PlantUmlBundle\Doctrine\EntityDecorator;
+use Irstea\PlantUmlBundle\Doctrine\EntityFinder;
+use Irstea\PlantUmlBundle\Finder\ClassFinder;
+use Irstea\PlantUmlBundle\Finder\FilteringFinder;
+use Irstea\PlantUmlBundle\Finder\FinderInterface;
 use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
 use Irstea\PlantUmlBundle\Model\ClassVisitor;
 use Irstea\PlantUmlBundle\Model\Decorator\CompositeDecorator;
@@ -23,6 +27,7 @@ use Irstea\PlantUmlBundle\Model\Filter\AcceptAllFilter;
 use Irstea\PlantUmlBundle\Model\Filter\Composite\AllFilter;
 use Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter;
 use Irstea\PlantUmlBundle\Model\Filter\NamespaceFilter;
+use Irstea\PlantUmlBundle\Model\Graph;
 use Irstea\PlantUmlBundle\Model\Namespace_\BundleNamespace;
 use Irstea\PlantUmlBundle\Model\Namespace_\FlatNamespace;
 use Irstea\PlantUmlBundle\Model\Namespace_\Php\RootNamespace;
@@ -98,102 +103,62 @@ class GenerateCommand extends ContainerAwareCommand
 
         $config = $graphs[$name];
 
-        $classes = $this->findClasses($config['sources']);
-        if (empty($classes)) {
-            $output->writeln("Nothing to analyze.");
-            return 0;
-        }
-
-        $namespace = $this->buildNamespace($config['layout']['namespaces']);
-        $displayFilter = $this->buildFilter($config['layout']);
-
-        $decorator = $this->buildDecorator($config['decoration']);
+        $graph = new Graph(
+            new ClassVisitor(
+                $this->buildDecorator($config['decoration']),
+                $this->buildFilter($config['layout']),
+                $this->buildNamespace($config['layout']['namespaces'])
+            ),
+            $this->buildFinder($config['sources'])
+        );
 
-        $visitor = new ClassVisitor($decorator, $displayFilter, $namespace);
-
-        foreach($classes as $class) {
-            $visitor->visitClass($class);
-        }
+        $graph->visitAll();
 
         $writer = new OutputWriter($output);
-        $writer->write("@startuml\n");
-        $visitor->outputTo($writer);
-        $writer->write("@enduml\n");
+        $graph->outputTo($writer);
     }
 
     /**
-     * @param ReflectionClass[]
+     * @param array $config
+     * @return FinderInterface
      */
-    protected function findClasses(array $config)
+    protected function buildFinder(array $config)
     {
         switch($config['type']) {
             case 'entities':
-                $classes = $this->findEntities($config['entity_manager']);
+                $finder = $this->buildEntityFinder($config['entity_manager']);
                 break;
             case 'classes':
-                $classes = $this->findClassesInDirectories($config['directories']);
+                $finder = $this->buildClassFinder($config['directories']);
                 break;
         }
 
         $filter = $this->buildFilter($config);
-        if ($filter) {
-            return array_filter($classes, [$filter, 'accept']);
+        if (!$filter) {
+            return $finder;
         }
 
-        return $classes;
+        return new FilteringFinder($finder, $filter);
     }
 
     /**
-     * @return ReflectionClass[]
+     * @param array $directories
+     * @return FinderInterface
      */
-    protected function findEntities($managerName)
+    protected function buildClassFinder(array $directories)
     {
-        $doctrine = $this->getContainer()->get('doctrine');
-        $this->entityManager = $doctrine->getManager($managerName);
-
-        $classes = [];
-        foreach($this->entityManager->getMetadataFactory()->getAllMetadata() as $metadata) {
-            $classes[$metadata->getName()] = $metadata->getReflectionClass();
-        }
-
-        return $classes;
+        return new ClassFinder($this->parseDirectories($directories));
     }
 
     /**
-     *
-     * @return ReflectionClass[]
+     * @param string $managerName
+     * @return FinderInterface
      */
-    protected function findClassesInDirectories($directories)
+    protected function buildEntityFinder($managerName)
     {
-        $paths = $this->parseDirectories($directories);
-
-        $files = Finder::create()
-            ->in($paths)
-            ->files()
-            ->name('*.php')
-            ->getIterator();
-
-        foreach($files as $file)
-        {
-            /* @var $file SplFileInfo */
-            $path = $file->getPathname();
-            try {
-                irstea_plantmul_include($path);
-            } catch(Exception $ex) {
-                printf("%s: %s (%s)\n", $path, get_class($ex), $ex->getMessage());
-            }
-        }
-
-        $filter = new DirectoryFilter($paths);
-        $classes = [];
-        foreach(get_declared_classes() as $className) {
-            $class = new ReflectionClass($className);
-            if ($filter->accept($class)) {
-                $classes[$className] = $class;
-            }
-        }
-
-        return $classes;
+        return new EntityFinder(
+            $this->getContainer()->get('doctrine')->getManager($managerName)
+        );
     }
 
     /**
@@ -203,32 +168,13 @@ class GenerateCommand extends ContainerAwareCommand
      */
     protected function buildDecorator(array $config)
     {
-        $decorators = [];
-
-        foreach($config['decorators'] as $decorator) {
-            switch($decorator) {
-                case 'inheritance':
-                    $decorators[] = new InheritanceDecorator();
-                    break;
-                case 'interfaces':
-                    $decorators[] = new InterfaceDecorator();
-                    break;
-                case 'traits':
-                    $decorators[] = new TraitDecorator();
-                    break;
-                case 'entity':
-                    $decorators[] = new EntityDecorator($this->entityManager->getMetadataFactory());
-                    break;
-                case 'associations':
-                    $decorators[] = new AssociationDecorator($this->entityManager->getMetadataFactory());
-                    break;
-                /*default:
-                    throw new RuntimeException("Decorator '$decorator' not yet implemented");*/
-            }
+        if (empty($config['decorators'])) {
+            return NullDecorator::instance();
         }
 
-        if (empty($decorators)) {
-            return NullDecorator::instance();
+        $decorators = [];
+        foreach($config['decorators'] as $type) {
+            $decorators[] = $this->buildTypedDecorator($type);
         }
 
         if (count($decorators) === 1) {
@@ -245,6 +191,26 @@ class GenerateCommand extends ContainerAwareCommand
         return $decorator;
     }
 
+    /**
+     * @param type $type
+     * @return DecoratorInterface
+     */
+    protected function buildTypedDecorator($type)
+    {
+        switch($type) {
+            case 'inheritance':
+                return new InheritanceDecorator();
+            case 'interfaces':
+                return new InterfaceDecorator();
+            case 'traits':
+                return new TraitDecorator();
+            case 'entity':
+                return new EntityDecorator($this->entityManager->getMetadataFactory());
+            case 'associations':
+                return new AssociationDecorator($this->entityManager->getMetadataFactory());
+        }
+    }
+
     /**
      * @param string $config
      * @return NamespaceInterface
@@ -340,9 +306,4 @@ class GenerateCommand extends ContainerAwareCommand
         return $actualNamespaces;
     }
 
-}
-
-function irstea_plantmul_include($filepath)
-{
-    @include_once($filepath);
 }
\ No newline at end of file
diff --git a/Doctrine/EntityFinder.php b/Doctrine/EntityFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b870cf6f39f3627ad64a8d4cfffd9f806f2839e
--- /dev/null
+++ b/Doctrine/EntityFinder.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Doctrine;
+
+use ArrayIterator;
+use Doctrine\ORM\EntityManager;
+use Irstea\PlantUmlBundle\Finder\FinderInterface;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class EntityFinder implements FinderInterface
+{
+    /**
+     * @var EntityManager
+     */
+    private $entityManager;
+
+    public function __construct(EntityManager $entityManager)
+    {
+        $this->entityManager = $entityManager;
+    }
+
+    public function getIterator()
+    {
+        $classes = [];
+        foreach($this->entityManager->getMetadataFactory()->getAllMetadata() as $metadata) {
+            $classes[$metadata->getName()] = $metadata->getReflectionClass();
+        }
+        return new ArrayIterator($classes);
+    }
+}
diff --git a/Finder/ClassFinder.php b/Finder/ClassFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..e89403466cd3f81737ae2be546d0e59502da76d8
--- /dev/null
+++ b/Finder/ClassFinder.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Finder;
+
+use ArrayIterator;
+use Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter;
+use ReflectionClass;
+use Symfony\Component\Config\Definition\Exception\Exception;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\SplFileInfo;
+
+/**
+ * Description of ClassFinder
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class ClassFinder implements FinderInterface
+{
+    /**
+     * @var string[]
+     */
+    private $directories;
+
+    /**
+     *
+     * @var \ReflectionClass
+     */
+    private $classes = null;
+
+    public function __construct($directories)
+    {
+        $this->directories = $directories;
+    }
+
+    private function initialize()
+    {
+        $files = Finder::create()
+            ->in($this->directories)
+            ->files()
+            ->name('*.php')
+            ->getIterator();
+
+        foreach($files as $file)
+        {
+            /* @var $file SplFileInfo */
+            $path = $file->getPathname();
+            try {
+                irstea_plantmul_include($path);
+            } catch(Exception $ex) {
+                printf("%s: %s (%s)\n", $path, get_class($ex), $ex->getMessage());
+            }
+        }
+
+        $filter = new DirectoryFilter($this->directories);
+        $this->classes = [];
+        foreach(get_declared_classes() as $className) {
+            $class = new ReflectionClass($className);
+            if ($filter->accept($class)) {
+                $this->classes[$className] = $class;
+            }
+        }
+    }
+
+    public function getIterator()
+    {
+        if ($this->classes === null) {
+            $this->initialize();
+        }
+        return new ArrayIterator($this->classes);
+    }
+}
+
+function irstea_plantmul_include($filepath)
+{
+    @include_once($filepath);
+}
diff --git a/Finder/FilteringFinder.php b/Finder/FilteringFinder.php
new file mode 100644
index 0000000000000000000000000000000000000000..e78fd868b83966ac526f2777fa5749b4065b4f6f
--- /dev/null
+++ b/Finder/FilteringFinder.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Finder;
+
+use CallbackFilterIterator;
+use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
+
+/**
+ * Description of FilteringFinder
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class FilteringFinder implements FinderInterface
+{
+    /**
+     * @var FinderInterface
+     */
+    private $inner;
+
+    /**
+     * @var ClassFilterInterface
+     */
+    private $filter;
+
+    public function __construct(FinderInterface $inner, ClassFilterInterface $filter)
+    {
+        $this->inner  = $inner;
+        $this->filter = $filter;
+    }
+
+    public function getIterator()
+    {
+        return new CallbackFilterIterator($this->inner->getIterator(), [$this->filter, 'accept']);
+    }
+}
diff --git a/Finder/FinderInterface.php b/Finder/FinderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..56657cd8fcde888557f355274dc2b3e2f55ff097
--- /dev/null
+++ b/Finder/FinderInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Finder;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+interface FinderInterface extends \Traversable, \IteratorAggregate
+{
+}
diff --git a/Model/ClassVisitor.php b/Model/ClassVisitor.php
index 1f557bc08da5c95421faa459e3cd8be9f0b48216..c793cf1311c1be347b6eedfd604031113cf4d7d9 100644
--- a/Model/ClassVisitor.php
+++ b/Model/ClassVisitor.php
@@ -23,7 +23,7 @@ use ReflectionClass;
  *
  * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
  */
-class ClassVisitor implements ClassVisitorInterface, WritableInterface
+class ClassVisitor implements ClassVisitorInterface
 {
     /**
      * @var NamespaceInterface
diff --git a/Model/ClassVisitorInterface.php b/Model/ClassVisitorInterface.php
index dbc6608022934facf36f3e89e092f958d59746ac..9ad017898ed85d72dfe850d07df1f357fdb477c5 100644
--- a/Model/ClassVisitorInterface.php
+++ b/Model/ClassVisitorInterface.php
@@ -8,13 +8,13 @@
 
 namespace Irstea\PlantUmlBundle\Model;
 
-use ReflectionClass;
+use Irstea\PlantUmlBundle\Writer\WritableInterface;
 
 /**
  *
  * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
  */
-interface ClassVisitorInterface
+interface ClassVisitorInterface extends WritableInterface
 {
     /**
      * @param ReflectionClass|string
diff --git a/Model/Graph.php b/Model/Graph.php
new file mode 100644
index 0000000000000000000000000000000000000000..9442c1fffe2233aaa25cae118b563117abbea3ec
--- /dev/null
+++ b/Model/Graph.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model;
+
+use Irstea\PlantUmlBundle\Finder\FinderInterface;
+use Irstea\PlantUmlBundle\Writer\WriterInterface;
+
+/**
+ * Description of Graph
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class Graph implements GraphInterface
+{
+    /**
+     * @var ClassVisitorInterface
+     */
+    private $visitor;
+
+    /**
+     * @var FinderInterface
+     */
+    private $finder;
+
+    public function __construct(ClassVisitorInterface $visitor, FinderInterface $finder)
+    {
+        $this->visitor = $visitor;
+        $this->finder  = $finder;
+    }
+
+    public function visitAll()
+    {
+        foreach($this->finder->getIterator() as $class) {
+            $this->visitor->visitClass($class);
+        }
+    }
+
+    public function outputTo(WriterInterface $writer)
+    {
+        $writer->write("@startuml@\n");
+        $this->visitor->outputTo($writer);
+        $writer->write("@enduml@\n");
+        return $this;
+    }
+}
diff --git a/Model/GraphInterface.php b/Model/GraphInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..e45bf8ae4bea800ac11fefcd1e83c6b5b42610f5
--- /dev/null
+++ b/Model/GraphInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model;
+
+use Irstea\PlantUmlBundle\Writer\WritableInterface;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+interface GraphInterface extends WritableInterface
+{
+    /**
+     * @return void
+     */
+    public function visitAll();
+}