Deep Dive into Creational Patterns - The Prototype Pattern.

Hey software designers! Today, we’re exploring the Prototype pattern. This pattern is a powerful tool for creating new objects by copying existing ones, offering flexibility and performance improvements. Let’s dive into its workings, benefits, and real-world applications with detailed examples.

What is the Prototype Pattern?

The Prototype pattern is a creational design pattern that allows you to create new objects by copying an existing object, known as the prototype. Instead of instantiating a new object from scratch, you clone the prototype, which can be more efficient and flexible, especially when creating objects that are resource-intensive to instantiate.

Real-World Scenario

Imagine you’re working on a game that includes various types of characters (warriors, mages, archers). Each character has different attributes and abilities, and creating them from scratch every time could be time-consuming and inefficient.

The Problem

When creating multiple instances of complex objects, instantiating each one from scratch can be resource-intensive and slow. Hardcoding the creation logic for each type of character can lead to duplication and inflexible code.

Without Prototype Pattern

class Warrior
  attr_accessor :name, :health, :attack_power

  def initialize(name, health, attack_power)
    @name = name
    @health = health
    @attack_power = attack_power
  end
end

warrior1 = Warrior.new('Aragon', 100, 50)
warrior2 = Warrior.new('Boromir', 100, 50)

Drawbacks: Duplicate initialization logic, inflexible and hard to maintain.

The Solution: Prototype Pattern

Using the Prototype pattern, we can create new instances by cloning existing ones, reducing the need for repetitive initialization logic and improving performance.

With Prototype Pattern

Step 1: Define the Prototype Interface

class CharacterPrototype
  def clone
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

Step 2: Create Concrete Prototypes

class Warrior < CharacterPrototype
  attr_accessor :name, :health, :attack_power

  def initialize(name, health, attack_power)
    @name = name
    @health = health
    @attack_power = attack_power
  end

  def clone
    Warrior.new(@name, @health, @attack_power)
  end
end

class Mage < CharacterPrototype
  attr_accessor :name, :health, :magic_power

  def initialize(name, health, magic_power)
    @name = name
    @health = health
    @magic_power = magic_power
  end

  def clone
    Mage.new(@name, @health, @magic_power)
  end
end

Step 3: Implement Client Code

warrior1 = Warrior.new('Aragon', 100, 50)
warrior2 = warrior1.clone
warrior2.name = 'Boromir'

mage1 = Mage.new('Gandalf', 80, 100)
mage2 = mage1.clone
mage2.name = 'Saruman'

puts warrior1.name # Aragon
puts warrior2.name # Boromir
puts mage1.name    # Gandalf
puts mage2.name    # Saruman

Real-World Benefits

Scenario: Creating Different Character Types

Imagine you need to create various character types (warriors, mages, archers) with different attributes. Using the Prototype pattern, you can easily clone existing characters and modify their attributes without writing repetitive code.

Without Prototype Pattern:

class CharacterFactory
  def create_warrior(name)
    Warrior.new(name, 100, 50)
  end

  def create_mage(name)
    Mage.new(name, 80, 100)
  end
end

factory = CharacterFactory.new
warrior1 = factory.create_warrior('Aragon')
warrior2 = factory.create_warrior('Boromir')

Drawbacks: Repetitive initialization logic, inflexible and hard to extend.

With Prototype Pattern:

prototype_warrior = Warrior.new('Prototype', 100, 50)
prototype_mage = Mage.new('Prototype', 80, 100)

warrior1 = prototype_warrior.clone
warrior1.name = 'Aragon'

warrior2 = prototype_warrior.clone
warrior2.name = 'Boromir'

mage1 = prototype_mage.clone
mage1.name = 'Gandalf'

mage2 = prototype_mage.clone
mage2.name = 'Saruman'

Benefits: Clean, maintainable code with high flexibility and efficiency.

Conclusion

The Prototype pattern is a powerful tool for creating new objects by copying existing ones. It promotes flexibility, efficiency, and maintainability in your code. By cloning existing objects, the Prototype pattern allows you to create complex objects without the need for repetitive initialization logic. Incorporate the Prototype pattern into your design strategies to build more robust and adaptable software systems.

Stay tuned for more insights into software design principles and patterns.

Thôi Lo Code Đi Kẻo Sếp nạt!