diff --git a/README.md b/README.md
index 4440728..88fe3cb 100644
--- a/README.md
+++ b/README.md
@@ -27,8 +27,6 @@ its event-driven model to react to changes and events happening.
 
 * [Quickstart example](#quickstart-example)
 * [Usage](#usage)
-  * [Factory](#factory)
-    * [createClient()](#createclient)
   * [Client](#client)
     * [Commands](#commands)
     * [Promises](#promises)
@@ -48,10 +46,9 @@ Docker API of your local docker daemon:
 
 ```php
 $loop = React\EventLoop\Factory::create();
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$client = new Clue\React\Docker\Client($loop);
 
-$client->imageSearch('clue')->then(function ($images) {
+$client->imageSearch('clue')->then(function (array $images) {
     var_dump($images);
 });
 
@@ -62,45 +59,28 @@ See also the [examples](examples).
 
 ## Usage
 
-### Factory
+### Client
 
-The `Factory` is responsible for creating your `Client` instance.
-It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage).
+The `Client` is responsible for assembling and sending HTTP requests to the Docker Engine API.
+It uses an HTTP client bound to the main [`EventLoop`](https://github.com/reactphp/event-loop#usage)
+in order to handle async requests:
 
 ```php
 $loop = React\EventLoop\Factory::create();
-$factory = new Factory($loop);
+$client = new Clue\React\Docker\Client($loop);
 ```
 
-If you need custom DNS, SSL/TLS or proxy settings, you can explicitly pass a
-custom [`Browser`](https://github.com/clue/php-buzz-react#browser) instance:
+If your Docker Engine API is not accessible using the default `unix:///var/run/docker.sock`
+Unix domain socket path, you may optionally pass an explicit URL like this:
 
-```php
-$factory = new Factory($loop, $browser);
 ```
-
-#### createClient()
-
-The `createClient($url = null)` method can be used to create a new `Client`.
-It helps with constructing a `Browser` object for the given remote URL.
-
-```php
-// create client with default URL (unix:///var/run/docker.sock)
-$client = $factory->createClient();
-
 // explicitly use given UNIX socket path
-$client = $factory->createClient('unix:///var/run/docker.sock');
+$client = new Clue\React\Docker\Client($loop, 'unix:///var/run/docker.sock');
 
-// connect via TCP/IP
-$client = $factory->createClient('http://10.0.0.2:8000/');
+// or connect via TCP/IP to a remote Docker Engine API
+$client = new Clue\React\Docker\Client($loop, 'http://10.0.0.2:8000/');
 ```
 
-### Client
-
-The `Client` is responsible for assembling and sending HTTP requests to the Docker API.
-It requires a `Browser` object bound to the main `EventLoop` in order to handle async requests and a base URL.
-The recommended way to create a `Client` is using the `Factory` (see above).
-
 #### Commands
 
 All public methods on the `Client` resemble the API described in the [Docker Engine API documentation](https://docs.docker.com/develop/sdk/) like this:
@@ -162,8 +142,7 @@ The resulting blocking code could look something like this:
 use Clue\React\Block;
 
 $loop = React\EventLoop\Factory::create();
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$client = new Clue\React\Docker\Client($loop);
 
 $promise = $client->imageInspect('busybox');
 
diff --git a/examples/archive.php b/examples/archive.php
index 4fd03c2..1a38719 100644
--- a/examples/archive.php
+++ b/examples/archive.php
@@ -1,24 +1,22 @@
 <?php
+
 // this example shows how the containerArchiveStream() method returns a TAR stream,
 // how it can be passed to a TAR decoder and how we can then pipe each
 // individual file to the console output.
 
-require __DIR__ . '/../vendor/autoload.php';
-
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+use Clue\CaretNotation\Encoder;
+use Clue\React\Docker\Client;
 use Clue\React\Tar\Decoder;
 use React\Stream\ReadableStreamInterface;
-use Clue\CaretNotation\Encoder;
+
+require __DIR__ . '/../vendor/autoload.php';
 
 $container = isset($argv[1]) ? $argv[1] : 'asd';
 $path = isset($argv[2]) ? $argv[2] : '/etc/passwd';
 echo 'Container "' . $container . '" dumping "' . $path . '" (pass as arguments to this example)' . PHP_EOL;
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $stream = $client->containerArchiveStream($container, $path);
 
diff --git a/examples/benchmark-exec.php b/examples/benchmark-exec.php
index 79b55ec..9f139f9 100644
--- a/examples/benchmark-exec.php
+++ b/examples/benchmark-exec.php
@@ -1,14 +1,13 @@
 <?php
+
 // this simple example executes a command within the given running container and
 // displays how fast it can receive its output.
 // expect this to be significantly faster than the (totally unfair) equivalent:
 // $ docker exec asd dd if=/dev/zero bs=1M count=1000 | dd of=/dev/null
 
-require __DIR__ . '/../vendor/autoload.php';
+use Clue\React\Docker\Client;
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
-use React\Stream\Stream;
+require __DIR__ . '/../vendor/autoload.php';
 
 $container = 'asd';
 $cmd = array('dd', 'if=/dev/zero', 'bs=1M', 'count=1000');
@@ -18,10 +17,8 @@
     $cmd = array_slice($argv, 2);
 }
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $client->execCreate($container, $cmd)->then(function ($info) use ($client) {
     $stream = $client->execStartStream($info['Id'], true);
diff --git a/examples/events.php b/examples/events.php
index 8750fb7..0f6d518 100644
--- a/examples/events.php
+++ b/examples/events.php
@@ -1,16 +1,14 @@
 <?php
+
 // this simple example displays all docker events that happen in the next 10s.
 // try starting / removing a container in the meantime to see some output.
 
-require __DIR__ . '/../vendor/autoload.php';
-
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+use Clue\React\Docker\Client;
 
-$loop = LoopFactory::create();
+require __DIR__ . '/../vendor/autoload.php';
 
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 // get a list of all events that happened up until this point
 // expect this list to be limited to the last 64 (or so) events
diff --git a/examples/exec-inspect.php b/examples/exec-inspect.php
index d13a33e..80b1bfc 100644
--- a/examples/exec-inspect.php
+++ b/examples/exec-inspect.php
@@ -1,11 +1,11 @@
 <?php
-// this simple example executes a "sleep 2" within the given running container
 
-require __DIR__ . '/../vendor/autoload.php';
+// this simple example executes a "sleep 2" within the given running container
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
 use Clue\React\Buzz\Message\ResponseException;
+use Clue\React\Docker\Client;
+
+require __DIR__ . '/../vendor/autoload.php';
 
 $container = 'asd';
 //$cmd = array('echo', 'hello world');
@@ -18,10 +18,8 @@
     $cmd = array_slice($argv, 2);
 }
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $client->execCreate($container, $cmd)->then(function ($info) use ($client) {
     echo 'Created with info: ' . json_encode($info) . PHP_EOL;
diff --git a/examples/exec-stream.php b/examples/exec-stream.php
index e288dcf..01f6403 100644
--- a/examples/exec-stream.php
+++ b/examples/exec-stream.php
@@ -1,13 +1,13 @@
 <?php
+
 // this example executes some commands within the given running container and
 // displays the streaming output as it happens.
 
-require __DIR__ . '/../vendor/autoload.php';
-
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+use Clue\React\Docker\Client;
 use React\Stream\Stream;
 
+require __DIR__ . '/../vendor/autoload.php';
+
 $container = 'asd';
 //$cmd = array('echo', 'hello world');
 //$cmd = array('sleep', '2');
@@ -19,10 +19,8 @@
     $cmd = array_slice($argv, 2);
 }
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $out = new Stream(STDOUT, $loop);
 $out->pause();
diff --git a/examples/export.php b/examples/export.php
index d69a6ec..752d53b 100644
--- a/examples/export.php
+++ b/examples/export.php
@@ -1,21 +1,19 @@
 <?php
+
 // this example shows how the containerExport() call returns a TAR stream
 // and how we it can be piped into a output tar file.
 
-require __DIR__ . '/../vendor/autoload.php';
-
-use React\EventLoop\StreamSelectLoop;
-use Clue\React\Docker\Factory;
+use Clue\React\Docker\Client;
 use React\Stream\Stream;
 
+require __DIR__ . '/../vendor/autoload.php';
+
 $container = isset($argv[1]) ? $argv[1] : 'asd';
 $target = isset($argv[2]) ? $argv[2] : ($container . '.tar');
 echo 'Exporting whole container "' . $container . '" to "' . $target .'" (pass as arguments to this example)' . PHP_EOL;
 
-$loop = new StreamSelectLoop();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $stream = $client->containerExportStream($container);
 
diff --git a/examples/info.php b/examples/info.php
index 304d3df..6738512 100644
--- a/examples/info.php
+++ b/examples/info.php
@@ -1,15 +1,13 @@
 <?php
-// this simple example displays system wide information from Docker as a simple JSON
 
-require __DIR__ . '/../vendor/autoload.php';
+// this simple example displays system wide information from Docker as a simple JSON
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+use Clue\React\Docker\Client;
 
-$loop = LoopFactory::create();
+require __DIR__ . '/../vendor/autoload.php';
 
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $client->info()->then(function ($info) {
     echo json_encode($info, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL;
diff --git a/examples/pull.php b/examples/pull.php
index 342d877..3fbc8a5 100644
--- a/examples/pull.php
+++ b/examples/pull.php
@@ -1,19 +1,17 @@
 <?php
+
 // this example shows how the imageCreateStream() call can be used to pull a given image.
 // demonstrates the JSON streaming API, individual progress events will be printed as they happen.
 
-require __DIR__ . '/../vendor/autoload.php';
+use Clue\React\Docker\Client;
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+require __DIR__ . '/../vendor/autoload.php';
 
 $image = isset($argv[1]) ? $argv[1] : 'clue/redis-benchmark';
 echo 'Pulling image "' . $image . '" (pass as argument to this example)' . PHP_EOL;
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $stream = $client->imageCreateStream($image);
 
diff --git a/examples/push.php b/examples/push.php
index 62b108c..5f5ca01 100644
--- a/examples/push.php
+++ b/examples/push.php
@@ -1,20 +1,18 @@
 <?php
+
 // this example shows how the imagePush() call can be used to publish a given image.
 // this requires authorization and this example includes some invalid defaults.
 
-require __DIR__ . '/../vendor/autoload.php';
+use Clue\React\Docker\Client;
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+require __DIR__ . '/../vendor/autoload.php';
 
 $image = isset($argv[1]) ? $argv[1] : 'asd';
 $auth = json_decode('{"username": "string", "password": "string", "email": "string", "serveraddress" : "string", "auth": ""}');
 echo 'Pushing image "' . $image . '" (pass as argument to this example)' . PHP_EOL;
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $client->imagePush($image, null, null, $auth)->then(function ($result) {
     echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL;
diff --git a/examples/resize.php b/examples/resize.php
index 32455a7..7d72c0a 100644
--- a/examples/resize.php
+++ b/examples/resize.php
@@ -1,18 +1,16 @@
 <?php
+
 // this example tries to adjust the TTY size of the given container to 10x10.
 // you can check this via "docker logs".
 
-require __DIR__ . '/../vendor/autoload.php';
+use Clue\React\Docker\Client;
 
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
+require __DIR__ . '/../vendor/autoload.php';
 
 $container = isset($argv[1]) ? $argv[1] : 'asd';
 
-$loop = LoopFactory::create();
-
-$factory = new Factory($loop);
-$client = $factory->createClient();
+$loop = React\EventLoop\Factory::create();
+$client = new Client($loop);
 
 $client->containerInspect($container)->then(function ($info) use ($client, $container) {
     $size = $info['HostConfig']['ConsoleSize'];
diff --git a/src/Client.php b/src/Client.php
index 55ab995..6c8ba26 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -3,9 +3,11 @@
 namespace Clue\React\Docker;
 
 use Clue\React\Buzz\Browser;
+use Clue\React\Buzz\Io\Sender;
 use Clue\React\Docker\Io\ResponseParser;
-use React\Promise\PromiseInterface;
 use Clue\React\Docker\Io\StreamingParser;
+use React\EventLoop\LoopInterface;
+use React\Promise\PromiseInterface;
 use React\Stream\ReadableStreamInterface;
 use Rize\UriTemplate;
 
@@ -30,35 +32,33 @@ class Client
     private $streamingParser;
     private $uri;
 
-    /**
-     * Instantiate new Client
-     *
-     * SHOULD NOT be called manually, see Factory::createClient() instead
-     *
-     * @param Browser              $browser         Browser instance to use, requires correct Sender and base URI
-     * @param ResponseParser|null  $parser          (optional) ResponseParser instance to use
-     * @param StreamingParser|null $streamingParser (optional) StreamingParser instance to use
-     * @param UriTemplate|null     $uri             (optional) UriTemplate instance to use
-     * @see Factory::createClient()
-     */
-    public function __construct(Browser $browser, ResponseParser $parser = null, StreamingParser $streamingParser = null, UriTemplate $uri = null)
+    public function __construct(LoopInterface $loop, $url = null)
     {
-        if ($parser === null) {
-            $parser = new ResponseParser();
+        if ($url === null) {
+            $url = 'unix:///var/run/docker.sock';
         }
 
-        if ($streamingParser === null) {
-            $streamingParser = new StreamingParser();
+        $browser = new Browser($loop);
+
+        if (substr($url, 0, 7) === 'unix://') {
+            // send everything through a local unix domain socket
+            $browser = $browser->withSender(
+                Sender::createFromLoopUnix($loop, $url)
+            );
+
+            // pretend all HTTP URLs to be on localhost
+            $url = 'http://localhost/';
         }
 
-        if ($uri === null) {
-            $uri = new UriTemplate();
+        $parts = parse_url($url);
+        if (!isset($parts['scheme'], $parts['host']) || ($parts['scheme'] !== 'http' && $parts['scheme'] !== 'https')) {
+            throw new \InvalidArgumentException('Invalid Docker Engine API URL given');
         }
 
-        $this->browser = $browser;
-        $this->parser = $parser;
-        $this->streamingParser = $streamingParser;
-        $this->uri = $uri;
+        $this->browser = $browser->withBase($url);
+        $this->parser = new ResponseParser();
+        $this->streamingParser = new StreamingParser();
+        $this->uri = new UriTemplate();
     }
 
     /**
diff --git a/src/Factory.php b/src/Factory.php
deleted file mode 100644
index d7a6b0e..0000000
--- a/src/Factory.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-namespace Clue\React\Docker;
-
-use React\EventLoop\LoopInterface;
-use Clue\React\Buzz\Browser;
-use Clue\React\Buzz\Io\Sender;
-
-/**
- * The Factory is responsible for creating your Client instance.
- * It also registers everything with the main EventLoop.
- */
-class Factory
-{
-    private $loop;
-    private $browser;
-
-    /**
-     * Instantiate the Factory
-     *
-     * If you need custom DNS, SSL/TLS or proxy settings, you can explicitly
-     * pass a custom Browser instance.
-     *
-     * @param LoopInterface $loop    the event loop
-     * @param null|Browser  $browser (optional) custom Browser instance to use
-     */
-    public function __construct(LoopInterface $loop, Browser $browser = null)
-    {
-        if ($browser === null) {
-            $browser = new Browser($loop);
-        }
-
-        $this->loop = $loop;
-        $this->browser = $browser;
-    }
-
-    /**
-     * Creates a new Client instance and helps with constructing the right Browser object for the given remote URL
-     *
-     * @param null|string $url (optional) URL to your (local) Docker daemon, defaults to using local unix domain socket path
-     * @return Client
-     */
-    public function createClient($url = null)
-    {
-        if ($url === null) {
-            $url = 'unix:///var/run/docker.sock';
-        }
-
-        $browser = $this->browser;
-
-        if (substr($url, 0, 7) === 'unix://') {
-            // send everything through a local unix domain socket
-            $browser = $this->browser->withSender(
-                Sender::createFromLoopUnix($this->loop, $url)
-            );
-
-            // pretend all HTTP URLs to be on localhost
-            $url = 'http://localhost/';
-        }
-
-        return new Client($browser->withBase($url));
-    }
-}
diff --git a/tests/ClientTest.php b/tests/ClientTest.php
index 0b604a1..6475d5d 100644
--- a/tests/ClientTest.php
+++ b/tests/ClientTest.php
@@ -2,13 +2,13 @@
 
 namespace Clue\Tests\React\Docker;
 
-use Clue\React\Docker\Client;
-use React\Promise\Deferred;
 use Clue\React\Buzz\Browser;
-use RingCentral\Psr7\Response;
-use Psr\Http\Message\ResponseInterface;
+use Clue\React\Docker\Client;
 use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
 use React\Promise;
+use React\Promise\Deferred;
+use RingCentral\Psr7\Response;
 
 class ClientTest extends TestCase
 {
@@ -29,7 +29,66 @@ public function setUp()
 
         $this->parser = $this->getMockBuilder('Clue\React\Docker\Io\ResponseParser')->getMock();
         $this->streamingParser = $this->getMockBuilder('Clue\React\Docker\Io\StreamingParser')->getMock();
-        $this->client = new Client($this->browser, $this->parser, $this->streamingParser);
+
+        $this->client = new Client($this->loop);
+
+        $ref = new \ReflectionProperty($this->client, 'browser');
+        $ref->setAccessible(true);
+        $ref->setValue($this->client, $this->browser);
+
+        $ref = new \ReflectionProperty($this->client, 'parser');
+        $ref->setAccessible(true);
+        $ref->setValue($this->client, $this->parser);
+
+        $ref = new \ReflectionProperty($this->client, 'streamingParser');
+        $ref->setAccessible(true);
+        $ref->setValue($this->client, $this->streamingParser);
+    }
+
+    /**
+     * @doesNotPerformAssertions
+     */
+    public function testCtor()
+    {
+        new Client($this->loop);
+    }
+
+    public function testCtorWithExplicitUnixPath()
+    {
+        $client = new Client($this->loop, 'unix://docker.sock');
+
+        $ref = new \ReflectionProperty($client, 'browser');
+        $ref->setAccessible(true);
+        $browser = $ref->getValue($client);
+
+        $ref = new \ReflectionProperty($browser, 'baseUri');
+        $ref->setAccessible(true);
+        $url = $ref->getValue($browser);
+
+        $this->assertEquals('http://localhost/', $url);
+    }
+
+    public function testCtorWithExplicitHttpUrl()
+    {
+        $client = new Client($this->loop, 'http://localhost:8001/');
+
+        $ref = new \ReflectionProperty($client, 'browser');
+        $ref->setAccessible(true);
+        $browser = $ref->getValue($client);
+
+        $ref = new \ReflectionProperty($browser, 'baseUri');
+        $ref->setAccessible(true);
+        $url = $ref->getValue($browser);
+
+        $this->assertEquals('http://localhost:8001/', $url);
+    }
+
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    public function testCtorWithInvalidUrlThrows()
+    {
+        new Client($this->loop, 'ftp://invalid');
     }
 
     public function testPing()
diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php
deleted file mode 100644
index 62b7e74..0000000
--- a/tests/FactoryTest.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-namespace Clue\Tests\React\Docker;
-
-use Clue\React\Docker\Factory;
-use React\EventLoop\Factory as LoopFactory;
-
-class FactoryTest extends TestCase
-{
-    private $loop;
-    private $browser;
-    private $factory;
-
-    public function setUp()
-    {
-        $this->loop = LoopFactory::create();
-        $this->browser = $this->getMockBuilder('Clue\React\Buzz\Browser')->disableOriginalConstructor()->getMock();
-        $this->factory = new Factory($this->loop, $this->browser);
-    }
-
-    /**
-     * @doesNotPerformAssertions
-     */
-    public function testCtorDefaultBrowser()
-    {
-        new Factory($this->loop);
-    }
-
-    public function testCreateClientUsesCustomUnixSender()
-    {
-        $this->browser->expects($this->once())->method('withSender')->will($this->returnValue($this->browser));
-        $this->browser->expects($this->once())->method('withBase')->will($this->returnValue($this->browser));
-
-        $client = $this->factory->createClient();
-
-        $this->assertInstanceOf('Clue\React\Docker\Client', $client);
-    }
-
-    public function testCreateClientWithHttp()
-    {
-        $this->browser->expects($this->never())->method('withSender');
-        $this->browser->expects($this->once())->method('withBase')->with($this->equalTo('http://localhost:1234/'))->will($this->returnValue($this->browser));
-
-        $this->factory->createClient('http://localhost:1234/');
-    }
-}
diff --git a/tests/FunctionalClientTest.php b/tests/FunctionalClientTest.php
index 1a3e71f..23adb87 100644
--- a/tests/FunctionalClientTest.php
+++ b/tests/FunctionalClientTest.php
@@ -2,11 +2,10 @@
 
 namespace Clue\Tests\React\Docker;
 
-use Clue\React\Docker\Client;
-use React\EventLoop\Factory as LoopFactory;
-use Clue\React\Docker\Factory;
 use Clue\React\Block;
+use Clue\React\Docker\Client;
 use Clue\React\Promise\Stream;
+use React\EventLoop\Factory as LoopFactory;
 
 class FunctionalClientTest extends TestCase
 {
@@ -15,10 +14,7 @@ class FunctionalClientTest extends TestCase
     public function setUp()
     {
         $this->loop = LoopFactory::create();
-
-        $factory = new Factory($this->loop);
-
-        $this->client = $factory->createClient();
+        $this->client = new Client($this->loop);
 
         $promise = $this->client->ping();
 
