{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Builder Pattern\n",
    "1. Creational Pattern\n",
    "1. Used to build complex objects\n",
    "1. Separates construction of an object from its representation\n",
    "1. It does that by encapsulating the object construction\n",
    "1. It even allows for multi step construction process\n",
    "1. Implementations can vary\n",
    "1. The client only sees the abstraction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Custom Computer Builder\n",
    "1. Has many components & hence can lead to bad design choices\n",
    "\n",
    "**Solutions**\n",
    "1. For too many parameters for a class - Attributes were exposed, instead of setting in the constructor\n",
    "1. For ordering - Attributes into methods, thereby enforcing assembly order\n",
    "1. Separated assembly into separate classes\n",
    "\n",
    "**Points**\n",
    "1. It separates 'How' from 'What'\n",
    "1. Assembly separate from components\n",
    "1. Encapsulates what varies - like the parts\n",
    "1. Permits different representation\n",
    "1. A top level builder uses specialized builders to achieve its target\n",
    "1. Builder adds parts\n",
    "1. Client receives the product from builder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from abc import ABCMeta, abstractmethod"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Computer():\n",
    "    _name = 'PC'\n",
    "    \n",
    "    def __init__(self, name):\n",
    "        self._name = name\n",
    "        \n",
    "    def display(self):\n",
    "        print(f'{self._name:>20}\\n----------------------------------')\n",
    "        print(f\"{'Case':>15}: {self.case}\")\n",
    "        print(f\"{'Mainboard':>15}: {self.mainboard}\")\n",
    "        print(f\"{'CPU':>15}: {self.cpu}\")\n",
    "        print(f\"{'Memory':>15}: {self.memory}\")\n",
    "        print(f\"{'Hard Drive':>15}: {self.hard_drive}\")\n",
    "        print(f\"{'Video Card':>15}: {self.video_card}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class IComputerBuilder(metaclass=ABCMeta):\n",
    "    def new_computer(self):\n",
    "        self._computer = Computer(self._name)\n",
    "    \n",
    "    def get_computer(self):\n",
    "        return self._computer\n",
    "    \n",
    "    @abstractmethod\n",
    "    def build_mainboard(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def get_case(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def install_mainboard(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def install_hard_drive(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def install_video_card(self):\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class GamingPCBuilder(IComputerBuilder):\n",
    "    _name = 'Gaming PC'\n",
    "    \n",
    "    def get_case(self):\n",
    "        self._computer.case = 'Coolermaster N300'\n",
    "        \n",
    "    def build_mainboard(self):\n",
    "        self._computer.mainboard = 'MSI 970'\n",
    "        self._computer.cpu = 'Intel Core i7840k'\n",
    "        self._computer.memory = 'Corsair Vengeance 16GB'\n",
    "        \n",
    "    def install_mainboard(self):\n",
    "        pass\n",
    "    \n",
    "    def install_hard_drive(self):\n",
    "        self._computer.hard_drive = 'Seagate 2TB'\n",
    "        \n",
    "    def install_video_card(self):\n",
    "        self._computer.video_card = 'GeForce GTX 1080 Ti'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class GenericPCBuilder(IComputerBuilder):\n",
    "    _name = 'Generic PC'\n",
    "    \n",
    "    def get_case(self):\n",
    "        self._computer.case = 'IN WIN BP655'\n",
    "        \n",
    "    def build_mainboard(self):\n",
    "        self._computer.mainboard = 'ASRock AMIH-ITX'\n",
    "        self._computer.cpu = 'AMD Athlon 5150'\n",
    "        self._computer.memory = 'Kingston ValueRAM 4GB'\n",
    "        \n",
    "    def install_mainboard(self):\n",
    "        pass\n",
    "    \n",
    "    def install_hard_drive(self):\n",
    "        self._computer.hard_drive = 'WD Blue 1TB'\n",
    "        \n",
    "    def install_video_card(self):\n",
    "        self._computer.video_card = 'On Board'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class ComputerBuilder():\n",
    "    def __init__(self, builder):\n",
    "        self._builder = builder\n",
    "        \n",
    "    def build_computer(self):\n",
    "        self._builder.new_computer()\n",
    "        self._builder.get_case()\n",
    "        self._builder.build_mainboard()\n",
    "        self._builder.install_mainboard()\n",
    "        self._builder.install_hard_drive()\n",
    "        self._builder.install_video_card()\n",
    "        \n",
    "    def get_computer(self):\n",
    "        return self._builder.get_computer()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Driver Program"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "           Gaming PC\n",
      "----------------------------------\n",
      "           Case: Coolermaster N300\n",
      "      Mainboard: MSI 970\n",
      "            CPU: Intel Core i7840k\n",
      "         Memory: Corsair Vengeance 16GB\n",
      "     Hard Drive: Seagate 2TB\n",
      "     Video Card: GeForce GTX 1080 Ti\n",
      "\n",
      "          Generic PC\n",
      "----------------------------------\n",
      "           Case: IN WIN BP655\n",
      "      Mainboard: ASRock AMIH-ITX\n",
      "            CPU: AMD Athlon 5150\n",
      "         Memory: Kingston ValueRAM 4GB\n",
      "     Hard Drive: WD Blue 1TB\n",
      "     Video Card: On Board\n",
      "\n"
     ]
    }
   ],
   "source": [
    "computer_builder = ComputerBuilder(GamingPCBuilder())\n",
    "computer_builder.build_computer()\n",
    "computer = computer_builder.get_computer()\n",
    "computer.display()\n",
    "\n",
    "computer_builder = ComputerBuilder(GenericPCBuilder())\n",
    "computer_builder.build_computer()\n",
    "computer = computer_builder.get_computer()\n",
    "computer.display()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}