By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
World of SoftwareWorld of SoftwareWorld of Software
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Search
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
Reading: Object Creation: The Issues I Faced and the Patterns That Helped Me | HackerNoon
Share
Sign In
Notification Show More
Font ResizerAa
World of SoftwareWorld of Software
Font ResizerAa
  • Software
  • Mobile
  • Computing
  • Gadget
  • Gaming
  • Videos
Search
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Have an existing account? Sign In
Follow US
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
World of Software > Computing > Object Creation: The Issues I Faced and the Patterns That Helped Me | HackerNoon
Computing

Object Creation: The Issues I Faced and the Patterns That Helped Me | HackerNoon

News Room
Last updated: 2025/09/04 at 7:15 PM
News Room Published 4 September 2025
Share
SHARE

Creational patterns were first described in the famous Gang of Four’s Design Patterns. The book presents each pattern in a dedicated chapter and follows a strict structure for each one: intent, motivation, applicability, structure, participants, collaborations, consequences, implementation, sample codes, known uses, and related patterns. The intent pattern presents a succinct goal of the pattern, while the applicability tells when you should use it.

For example, here’s an excerpt for the Builder pattern:

Intent:

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Applicability:

Use the Builder pattern when

  • the algorithm for creating a complex object should be independent of the Parts that make up the object and how they’re assembled.
  • the construction process must allow different representations for the object that’s constructed.

The GoF (Gang of Four) has been foundational in the domain of Object-Oriented Programming and has influenced the design of programming languages, including widespread ones such as Java. However, it may come as intimidating or irrelevant to modern software development.

As I’m back in an engineering position, I come across newly written Java code that has a lot of improvement potential regarding maintainability. It works, but I imagine engineers having to update it, including the original author’s future self and me, and I’m sure I can help them. This week, I refactored code using creational patterns to improve its maintainability. In this post, I want to describe the issues I faced and mention how patterns helped me.

A constructor with many parameters of the same type.

Let’s imagine a constructor with many String parameters:

public License (
    String id, String licenseeName,
    String licenseId, String environment,
    LocalDateTime generatedAt
)

When calling this constructor, chances are the caller may unwillingly switch parameter orders:

var license = new License("My license", "XXX-123", "Customer", "User-acceptance tests", new LocalDateTime());

Oops, I switched the licensee name and the license ID. Your IDE may help here, but there are other ways.

Type Wrappers

Proponents of pure OOP will happily point out that one should never directly use a string. Instead, one should wrap each parameter in a dedicated type, e.g., a Java record:

public record Id(String id) { ... }
public record LicenseeName(String licenseeName) { ... }
public record LicenseeId(String licenseId) { ... }
public record Environment(String environment) { ... }
public record GeneratedAt(LocalDateTime generatedAt) { ... }

Now, we can’t make a mistake:

var id = new Id("My license");
var licenseeName = new LicenseeName("Customer");
var licenseId = new LicenseeId("XXX-123");
var environment = new Environment("User-acceptance tests");
var generatedAt = new LocalDateTime();

var license = new License(id, licenseId, licenseName, environment, generatedAt); //1
  1. Compile-time error

While this approach definitely improves maintainability, the wrapper increases the memory size. The exact increase depends on the JDK implementation, but for a single type, it’s around 5 times larger.

Kotlin makes it a breeze by providing inline value classes: the wrapping is a compile-time check, but the bytecode points to the wrapped type with the following limitation:

An inline class must have a single property initialized in the primary constructor

Named Parameters

Java offers only method calls with positional parameters, but other languages, e.g., Python, Kotlin, and Rust, also offer named parameters.

Here’s a Kotlin constructor that mirrors the above class:

class License (
    val id: String, val licenseeName: String,
    val licenseId: String, val environment: String,
    val generatedAt: LocalDateTime
)

You can call the constructor by naming the parameters, thus reducing the risks of making a mistake:

val license = License(
    id = "My license", licenseeName = "Customer",
    licenseId = "XXX-123", environment = "User-acceptance tests",
    generatedAt = LocalDateTime()
)

The Builder Pattern

The Builder pattern is another viable approach, even though it’s not part of the use cases described in the GoF.

Here’s the code:

public class License {

    private final String id;
    private final String licenseeName;
    private final String licenseId;
    private final String environment;
    private final LocalDateTime generatedAt;

    private License (                              //1
        String id, String licenseeName,
        String licenseId, String environment,
        LocalDateTime generatedAt
    ) { ... }

    public static LicenseBuilder builder() {       //2
        return new LicenseBuilder();
    }

    public static class LicenseBuilder {

        private String id;                         //3
        private String licenseeName;               //3
        private String licenseId;                  //3
        private String environment;                //3
        private LocalDateTime generatedAt;         //3

        private LicenseBuilder() {}                //1

        public LicenseBuilder withId(String id) {  //4
            this.id = id;                          //5
            return this;                           //4
        }

        // Other `withXXX` methods

        public License build() {                   //6
            return new License(
                id, licenseeName,
                licenseId, environment,
                generatedAt
            );
        }
    }
}
  1. Prevent direct object instantiation
  2. Create a new builder
  3. The builder fields mimic the object’s fields
  4. Each method returns the builder object itself
  5. Assign the attribute
  6. Return the complete object

One can now call the builder as such:

val license = License.builder()
                     .withId("My license")
                     .withLicenseName("Customer")
                     .withLicenseId("XXX-123")
                     .withEnvironment("User-acceptance tests")
                     .withGeneratedAt(new LocalDateTime())

Creating the builder code is a pain (unless you use AI), but it allows for better readability. Moreover, one can add validation for every method call, ensuring the object under construction is valid. For more complex objects, one can also implement a Faceted Builder.

Summary

| Approach | Pros | Cons |
|—-|—-|—-|
| Type wrappers | Object-Oriented Programming | – More verbose- Can be memory-heavy depending on the language |
| Named parameters | Easy | Not available in Java |
| Builder pattern | Verbose | – Allows creating complex objects- Allows validating |

Constructors Throwing Exceptions

In the same codebase, I found the following code:

public Stuff(UuidService uuidService, FallbackUuidService fallbackUuidService) {

    try {
        uuid = uuidService.getUuid();
    } catch(CannotGetUuidException e) {
        try {
            uuid = fallbackUuidService.getUuid();
        } catch(CannotGetUuidException e1) {
            uuid = "UUID can be fetched";
        }
    }
}

With a modicum of experience, you can notice what’s wrong in the above snippet. If both services fail, uuid is initialized with a string that’s not a UUID. All code that relies on UUID must deal with possibly non-UUID values. One must fail fast. A quick fix would look like this:

public Stuff(UuidService uuidService, FallbackUuidService fallbackUuidService) {

    try {
        uuid = uuidService.getUuid();
    } catch(CannotGetUuidException e) {
        try {
            uuid = fallbackUuidService.getUuid();
        } catch(CannotGetUuidException e1) {
            throw new RuntimeException(e1);
        }
    }
}

Now, every Stuff object has a valid UUID. However, throwing exceptions inside constructors has potential issues:

  • Resource Leaks: If the constructor allocates resources (e.g., files, sockets) and throws an exception, those resources may not be released. It can be mitigated by being careful and using try-catch-finally blocks.
  • Inheritance: If a superclass constructor throws an exception, the subclass constructor won’t run.
  • Checked exceptions: It’s impossible to use checked exceptions in constructors, only runtime ones.

For these reasons, I think exceptions don’t have their place in constructors and I avoid them. One can use the Builder pattern described in the first section, but as mentioned, it’s a lot of code; I don’t think it’s necessary. Another creational pattern to the rescue, Factory Method.

Intent

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Applicability

Use the Factory Method pattern when:

  • a class can’t anticipate the class of objects it must create.
  • a class wants its subclasses to specify the objects it creates.
  • classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.

Note that in this case, we use it for a different reason. Here’s the updated code:

public class Stuff {

    private final UUID uuid;

    private Stuff(UUID uuid) {                               //1
        this.uuid = uuid;
    }

    public static Stuff create(UuidService uuidService, FallbackUuidService fallbackUuidService) throws CannotGetUuidException {

        try {
            return new Stuff(uuidService.getUuid());
        } catch(CannotGetUuidException e) {
            return new Stuff(fallbackUuidService.getUuid()); //2
        }
    }
}
  1. Prevent outside instantiation
  2. If it fails, it throws a new CannotGetUuidException

One calls the above like this:

var stuff = Stuff.create(uuidService, fallbackUuidService);  //1
  1. Need to catch CannotGetUuidException

At this point, we are sure that the object is fully initialized if the call succeeds. If it doesn’t, no object is created.

Conclusion

In this post, I’ve described two usages of the GoF’s creational patterns, which aren’t listed in the book: improving maintainability and ensuring objects are fully initialized. Knowing your classics allows you to use them in cases that fit, but weren’t initially listed for.

To go further:

  • GoF Design Patterns
  • A dive into the Builder pattern
  • The Builder pattern is a finite state machine!

Originally published at A Java Geek on August 31st, 2025

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Twitter Email Print
Share
What do you think?
Love0
Sad0
Happy0
Sleepy0
Angry0
Dead0
Wink0
Previous Article Android Studio Narwhal Extends Gemini AI Capabilities
Next Article Treat yourself and save 35% on this Ninja Foodi MAX 14-in-1 SmartLid Multi Cooker
Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Stay Connected

248.1k Like
69.1k Follow
134k Pin
54.3k Follow

Latest News

Nova Launcher is shutting down, and Android fans are heartbroken
News
How to Write a Real Estate Business Plan That Gets Results
Computing
Why Are We So Obsessed With Thin Screen Bezels?
News
Titans vs. Broncos Livestream: How to Watch NFL Week 1 Online Today
News

You Might also Like

Computing

How to Write a Real Estate Business Plan That Gets Results

27 Min Read
Computing

B2B Marketing Examples: Inspiring Strategies for Business Growth

24 Min Read
Computing

How to Use ChatGPT API for Your Applications |

22 Min Read
Computing

Free Influencer Contract Templates to Protect Your Brand Deals

24 Min Read
//

World of Software is your one-stop website for the latest tech news and updates, follow us now to get the news that matters to you.

Quick Link

  • Privacy Policy
  • Terms of use
  • Advertise
  • Contact

Topics

  • Computing
  • Software
  • Press Release
  • Trending

Sign Up for Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

World of SoftwareWorld of Software
Follow US
Copyright © All Rights Reserved. World of Software.
Welcome Back!

Sign in to your account

Lost your password?