Skip to content

BP1 - Gun (Iterator) - Design Pattern From Simple Things

There are bullets that need to be fired one by one in a specific order. You need a tool to set it up neatly and easily upgrade later.

3 min read
BP1 - Gun (Iterator) - Design Pattern From Simple Things

Gun (Iterator) is a behavioral design pattern: 🖤🖤🖤🖤🤍

Iterator and Iterable often confused me, so I renamed them. Gun represents Iterator, Bullets represents Iterable.

What is Gun and Bullets?

  • Bullets (Iterable) is a group of bullets.
    • def __iter__() helps us arrange bullets and other accessories to turn them into a gun.
  • Gun (Iterator) is an object that can fire bullet one by one.
    • def __next__() help us fire the bullets.
Gun Diagram

Why use Gun?

It makes shooting more manageable, more professional. Your gun can integrate other tools such as a compass, binoculars, and silencer…!

Question: Just throw the bullet to the target, the gun seems to just make it fancy!

Answer: It is more useful when you need to use plugins or customize many features with your gun.

Girl throw stone

When to use Gun?

Question: When I need to use Gun?

Answer: When you need to fire the bullets!

Input:

  • Having many bullets:
    • 1stBullet
    • 2ndBullet
    • 3rdBullet
# nothing here

Expected Output:

  • Firing bullets in expected order by:
    • Getting a Normal Gun
      • First Shoot will fire 1stBullet
      • Then 2ndBullet, 3rdBullet
    • Getting a LIFO Gun
      • First Shoot will fire 3rdBullet
      • Then 2ndBullet, 1stBullet
⬅️ Normal Gun 🔫:
🎯First Shoot: 1stBullet 
🎯The Rest: 2ndBullet-3rdBullet
🔄 LIFO Gun 🔫:
🎯First Shoot: 3rdBullet 
🎯The Rest: 2ndBullet-1stBullet
Gun and Bullets

How to implement Gun?

Non-Gun implementation:

if __name__ == "__main__":
    bullets = []
    # Input 1: Having many bullets:
    bullets.append("1stBullet")
    bullets.append("2ndBullet")
    bullets.append("3rdBullet")

    gun = iter(bullets)
    first_fired_bullet = next(gun)
    remaining_bullets = "-".join(gun)
    # Expected Output 1: Firing bullets in expected order by: Normal Gun
    print(
        f"⬅️ Normal Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
    )

    lifo_gun = iter(bullets[::-1])
    first_fired_bullet = next(lifo_gun)
    remaining_bullets = "-".join(lifo_gun)
    # Expected Output 2: Firing bullets in expected order by: LIFO Gun
    print(
        f"🔄 LIFO Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
    )

Gun implementation:

from collections.abc import Iterable, Iterator


class Bullets(Iterable):
    def __init__(self, bullets=None):
        self._bullets = bullets or []

    # to_normal_gun
    def __iter__(self):
        return Gun(self._bullets)

    def to_lifo_gun(self):
        return Gun(self._bullets, reverse=True)

    def load(self, bullet):
        self._bullets.append(bullet)


class Gun(Iterator):
    _position = None
    _reverse = False

    def __init__(self, bullets, reverse=False):
        self._bullets = bullets
        self._reverse = reverse
        self._position = -1 if reverse else 0

    def __next__(self):
        try:
            value = self._bullets[self._position]
            self._position += -1 if self._reverse else 1
        except IndexError:
            raise StopIteration()
        return value


if __name__ == "__main__":
    bullets = Bullets()
    # Input 1: Having many bullets:
    bullets.load("1stBullet")
    bullets.load("2ndBullet")
    bullets.load("3rdBullet")

    gun = iter(bullets)
    first_fired_bullet = next(gun)
    remaining_bullets = "-".join(gun)
    # Expected Output 1: Firing bullets in expected order by: Normal Gun
    print(
        f"⬅️ Normal Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
    )

    lifo_gun = bullets.to_lifo_gun()
    first_fired_bullet = next(lifo_gun)
    remaining_bullets = "-".join(lifo_gun)
    # Expected Output 2: Firing bullets in expected order by: LIFO Gun
    print(
        f"🔄 LIFO Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
    )

Source Code

Related posts

You found a tiny easter egg. Keep poking around!