The Palos Publishing Company

Follow Us On The X Platform @PalosPublishing
Categories We Write About

Designing a Payment Splitter App Using OOD Concepts

When designing a payment splitter app using Object-Oriented Design (OOD) concepts, the goal is to create a system that is modular, extensible, and easy to maintain. A payment splitter app allows multiple users to split a bill or cost evenly or in custom proportions, making it easy to share expenses like dining bills, travel expenses, etc.

Here’s how you can design the system step by step using OOD principles:

1. Identify Core Entities and Responsibilities

The first step in OOD is identifying the entities in your system and understanding their responsibilities. For a payment splitter app, the primary entities could be:

  • User: Represents a person who will participate in splitting payments.

  • Bill: Represents a bill that needs to be split.

  • Payment: Represents the payment made towards the bill.

  • SplitStrategy: Defines the method by which the bill is divided (evenly, by percentage, custom).

2. Define Relationships Between Entities

  • User can participate in multiple Bills.

  • A Bill is linked to multiple Payments.

  • A Bill will have a SplitStrategy that dictates how the total amount is divided among the users.

3. Design the Classes and Their Responsibilities

Now, let’s define the classes based on the identified entities:

Class: User

python
class User: def __init__(self, user_id, name): self.user_id = user_id self.name = name self.payments_made = [] # List of payments made by this user def add_payment(self, payment): self.payments_made.append(payment)
  • Attributes:

    • user_id: Unique identifier for each user.

    • name: Name of the user.

    • payments_made: List to store all payments made by the user.

  • Methods:

    • add_payment(payment): Adds a payment to the user’s list of payments.

Class: Bill

python
class Bill: def __init__(self, bill_id, amount, date): self.bill_id = bill_id self.amount = amount # Total amount of the bill self.date = date self.users = [] # Users involved in splitting the bill self.payments = [] # Payments made towards the bill self.split_strategy = None # The strategy used for splitting the bill def add_user(self, user): self.users.append(user) def add_payment(self, payment): self.payments.append(payment) def set_split_strategy(self, split_strategy): self.split_strategy = split_strategy def calculate_split(self): return self.split_strategy.calculate_split(self)
  • Attributes:

    • bill_id: Unique identifier for the bill.

    • amount: The total bill amount.

    • date: The date the bill was generated.

    • users: List of users involved in splitting the bill.

    • payments: List of payments made by the users.

    • split_strategy: Defines how the bill should be split among users.

  • Methods:

    • add_user(user): Adds a user to the bill.

    • add_payment(payment): Adds a payment made by a user.

    • set_split_strategy(split_strategy): Sets the split strategy for the bill.

    • calculate_split(): Calls the strategy to calculate the split for each user.

Class: Payment

python
class Payment: def __init__(self, user, amount, bill): self.user = user # The user making the payment self.amount = amount # Amount paid by the user self.bill = bill # The bill for which the payment was made def __str__(self): return f"{self.user.name} paid {self.amount} for bill {self.bill.bill_id}"
  • Attributes:

    • user: The user who made the payment.

    • amount: The amount paid.

    • bill: The bill that the payment is associated with.

Class: SplitStrategy (Abstract)

python
from abc import ABC, abstractmethod class SplitStrategy(ABC): @abstractmethod def calculate_split(self, bill): pass

This class serves as an abstract base class for different splitting strategies (even, percentage-based, custom). It contains the method calculate_split(), which will be implemented by subclasses.

Class: EvenSplitStrategy

python
class EvenSplitStrategy(SplitStrategy): def calculate_split(self, bill): users_count = len(bill.users) if users_count == 0: return {} split_amount = bill.amount / users_count return {user: split_amount for user in bill.users}
  • calculate_split(): Splits the total bill evenly among all users.

Class: PercentageSplitStrategy

python
class PercentageSplitStrategy(SplitStrategy): def __init__(self, percentages): self.percentages = percentages # A dictionary of users and their percentages def calculate_split(self, bill): splits = {} for user in bill.users: if user in self.percentages: splits[user] = bill.amount * self.percentages[user] / 100 else: splits[user] = 0 return splits
  • calculate_split(): Splits the bill based on predefined percentages for each user.

Class: CustomSplitStrategy

python
class CustomSplitStrategy(SplitStrategy): def __init__(self, custom_amounts): self.custom_amounts = custom_amounts # A dictionary of users and their custom amounts def calculate_split(self, bill): splits = {} for user in bill.users: if user in self.custom_amounts: splits[user] = self.custom_amounts[user] else: splits[user] = 0 return splits
  • calculate_split(): Custom splits based on the amounts specified for each user.

4. Implementing the Payment Splitter Logic

Once the classes and their relationships are defined, the app’s core logic can be implemented by combining these entities.

  1. Create Users: Initialize user objects.

  2. Create Bill: Create a bill object and set the total amount.

  3. Set Split Strategy: Choose a split strategy (even, percentage, or custom).

  4. Add Payments: Users make payments towards the bill.

  5. Calculate Splits: Use the split strategy to calculate how much each user owes.

5. Example of Usage

python
# Create users alice = User(user_id=1, name="Alice") bob = User(user_id=2, name="Bob") # Create a bill bill = Bill(bill_id=101, amount=100, date="2025-07-16") # Add users to the bill bill.add_user(alice) bill.add_user(bob) # Choose an even split strategy even_split_strategy = EvenSplitStrategy() bill.set_split_strategy(even_split_strategy) # Calculate the split split = bill.calculate_split() print(split) # Output: {'Alice': 50.0, 'Bob': 50.0} # Add payments payment1 = Payment(user=alice, amount=50, bill=bill) payment2 = Payment(user=bob, amount=50, bill=bill) bill.add_payment(payment1) bill.add_payment(payment2) # Display payments print(payment1) # Output: Alice paid 50 for bill 101 print(payment2) # Output: Bob paid 50 for bill 101

6. Conclusion

By using Object-Oriented Design principles, we have created a flexible and extendable system that can be easily modified to support new split strategies or additional features in the future (such as applying discounts, handling multiple bills, or integrating payment gateways). The key design concepts—such as inheritance (for split strategies), encapsulation (for user and payment information), and abstraction (for splitting logic)—ensure that the system is clean, scalable, and easy to understand.

Share this Page your favorite way: Click any app below to share.

Enter your email below to join The Palos Publishing Company Email List

We respect your email privacy

Categories We Write About