Lesson 4
Applying Creational Patterns in Ruby Banking System
Applying Creational Patterns in Banking System

Welcome back! You've learned so much about creational patterns, and it's time to apply this knowledge to a real-world project: a banking system. In this unit, we'll focus on using creational patterns to manage and simplify the creation of banking system components in Ruby.

Quick Pattern Refresher

Before we dive in, let's quickly recap the creational patterns we'll use:

  1. Singleton Pattern: Ensures a class has only one instance and provides a global point of access to it. We'll be using Ruby's built-in Singleton module for this purpose.
  2. Factory Method Pattern: Defines an interface for creating an object but allows subclasses to alter the type of objects that will be created. You'll see how Ruby's flexibility enhances the implementation of this pattern.
  3. Builder Pattern: Separates the construction of a complex object from its representation, allowing the same construction process to create various representations. We'll use it to add further modularity and customization to our system.

We will implement these patterns to create a logger and various types of accounts for our banking system.

What You'll Build

Let's see what you'll build in this unit. You will create:

  1. Logger with the Singleton Pattern: A logging mechanism that ensures only one instance of the logger exists throughout the application.

    Ruby
    1require 'singleton' 2 3class Logger 4 include Singleton 5 6 def log(message) 7 puts "Log: #{message}" 8 end 9end
  2. Accounts using the Factory Method Pattern: Different types of accounts (savings and current) created via a factory method.

    Ruby
    1class Account 2 def initialize(balance) 3 @balance = balance 4 end 5 6 def details 7 raise 'Abstract Method Called' 8 end 9end 10 11class SavingsAccount < Account 12 def details 13 "Savings Account with balance: #{@balance}" 14 end 15end 16 17class CurrentAccount < Account 18 def details 19 "Current Account with balance: #{@balance}" 20 end 21end 22 23class AccountFactory 24 def self.create_account(type, balance) 25 case type 26 when :savings 27 SavingsAccount.new(balance) 28 when :current 29 CurrentAccount.new(balance) 30 else 31 raise 'Unknown account type' 32 end 33 end 34end
  3. Builder Pattern for Account Reports: A demonstration of using the Builder Pattern to create detailed account reports.

    Ruby
    1class AccountReport 2 attr_accessor :owner_name, :account_number, :balance, :report_date 3 4 def details 5 "Account Report for #{owner_name} - Account Number: #{account_number}, Balance: #{balance}, Date: #{report_date}" 6 end 7end 8 9class AccountReportBuilder 10 def initialize 11 @report = AccountReport.new 12 end 13 14 def set_owner_name(name) 15 @report.owner_name = name 16 self 17 end 18 19 def set_account_number(number) 20 @report.account_number = number 21 self 22 end 23 24 def set_balance(balance) 25 @report.balance = balance 26 self 27 end 28 29 def set_report_date(date) 30 @report.report_date = date 31 self 32 end 33 34 def build 35 @report 36 end 37end
  4. Code Integration: Comprehensive integration of these patterns into a cohesive system using Singleton, Factory Method, and Builder patterns.

    Example usage:

    Ruby
    1# Singleton Logger 2logger = Logger.instance 3logger.log('System started.') 4 5# Factory Method for creating accounts 6account1 = AccountFactory.create_account(:savings, 1000) 7account2 = AccountFactory.create_account(:current, 500) 8 9logger.log(account1.details) 10logger.log(account2.details) 11 12# Builder Pattern for account reports 13report_builder = AccountReportBuilder.new 14report = report_builder.set_owner_name('Jane Doe') 15 .set_account_number('123456789') 16 .set_balance(1500) 17 .set_report_date(Date.today) 18 .build 19 20logger.log(report.details)

While these patterns provide significant benefits in modularity and flexibility, they also introduce additional layers of abstraction, which can increase code complexity. To mitigate this, ensure that each pattern is applied only when its advantages clearly outweigh its costs. For instance, avoid using the Builder Pattern for simple objects that don’t require step-by-step construction.

Ready to start building? Let's dive into the implementation together!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.