Manager/Builder pattern
This module exposes a class making it easier to implement builder pattern to your classes.
Table of contents
Usage
Install the package from npm as follows:
npm i @poppinss/manager
yarn add @poppinss/manager
and then import it as follows. Check How it works section for complete docs
import { Manager, ManagerContract } from '@poppinss/manager'
How it works?
Builder pattern is a way to compose objects by hiding most of their complexities. Similarly, the Manager pattern also manages the lifecycle of those objects, after composing them.
AdonisJs heavily makes use of this pattern in modules like Mail
, Auth
, Session
and so on, where you can switch between multiple drivers, without realizing the amount of work done behind the scenes.
Let's see how the driver's based approach works without the Manager pattern.
Drivers
class SessionRedisDriver {
public write () {}
public read () {}
}
class SessionFileDriver {
public write () {}
public read () {}
}
Session main class
class Session {
constructor (private _driver) {
}
put () {
this._driver.put()
}
}
Usage
Now, you can use it as follows.
const file = new SessionFileDriver()
const session = new Session(file)
session.put('')
The above example is very simple and may feel fine at first glance. However, you may face following challenges.
- It is not easy to switch drivers, since you have to manually re-create the driver and then create instance of the session class.
- If you want to use singleton instances, then you need to wrap all this code inside a seperate file, that exports the singleton.
- If creating a driver has more dependencies, then you will have to construct all those dependencies by hand.
Using Manager class
Continuing to the same example, let's create a Manager class that abstracts away all of this manual boilerplate.
import { Manager } from '@poppinss/manager'
class SessionManager extends Manager<Session> {
protected getDefaultDriverName () {
return 'file'
}
protected $cacheDrivers = true
protected createFile () {
return new Session(new SessionFileDriver())
}
protected createRedis () {
return new Session(new SessionRedisDriver())
}
}
and now, you can use it as follows.
const session = new SessionManager()
session.driver('file')
session.driver('redis')
Adding drivers from outside
Also, the session manager can be extended to add more dynamic drivers. Think of accepting plugins to add drivers.
const session = new SessionManager()
session.extend('mongo', () => {
return new SessionMongoDriver()
})
session.driver('mongo')
Autocomplete drivers list
Also, you can pass a union to the Manager
constructor and it will typehint the list of drivers for you.
class SessionManager extends Manager<
Session,
{ file: SessionFileDriver, redis: SessionRedisDriver },
> {
}
new SessionManager
.driver('')
Drivers types
Along with the runtime code to extend and fetch drivers, we also ship the types to deal with static side of things as well.
Since the process of having extensible drivers with type information requires some complex types structure, we recommend you to look at example/index.ts file for a complete example.
API Docs
Following are the autogenerated files via Typedoc
Maintainers
Harminder virk
`