Pragmatic Objects
  • Pragmatic Objects
  • What's an Object ?
  • Thinking Object
  • Practices
    • The Pragmatic Practices
    • No Getters & Setters
    • Inherit Wisely
    • Wrap Null
    • Wrap Primitives
    • Wrap Collections
    • Expose Snapshots
    • Abandon Composed Names
    • Don't Check Types
    • Minimize Knowledge
    • Immutability
    • Separate Commands & Queries
    • Abandon Statics
    • Invert Dependencies
  • Patterns
    • Domain Model
    • Always Valid
    • Wrapper
    • Command
    • Procedural Object
    • Compute Object
    • Snapshot
    • Value Object
    • Observability
  • Examples
    • Celsiuses / Fahrenheits
Powered by GitBook
On this page
  1. Patterns

Wrapper

Wrap an object to enable decoration

A wrapper, as the name suggest, wraps an object or a value. To this regard, it is a generalization of the Value Object.

But the Wrapper exposes a single method such as expose and enable composition to perform operations on objects.

Using wrappers allow to pick specific decorators for the task at hand, in which each decorator is a Compute Object, except for the wrapped value which often is a Value Object.

interface IWrapped<T> {
  expose(): T;
}

class Identity<T> implements IWrapped<T> {
  constructor(private readonly value: T) {}
  expose() {
    return this.value;
  }
}

abstract class Wrapper<T> implements IWrapped<T> {
  constructor(protected readonly value: IWrapped<T>) {}
  abstract expose(): T;
}

class LowerCase extends Wrapper<string> {
  expose() {
    return this.value.expose().toLowerCase();
  }
}

class Slugify extends Wrapper<string> {
  expose() {
    return this.value
      .expose()
      .replace(' ', '-')
      .replace(/[^a-zA-Z0-9-]/g, '');
  }
}

const result = 
    new Slugify(
        new LowerCase(
            new Identity('Hello World')
        ),
    ).expose();

expect(result).toBe('hello-world');
PreviousAlways ValidNextCommand

Last updated 1 year ago