ファクトリーメソッドとは
ファクトリーメソッド(Factory Method)は、オブジェクトを作るときに、必要な加工や整形もまとめて行う仕組みです。
単に特定の式を指すのではなく、受け取ったデータを加工・整形して、使いやすいインスタンスを返す一連の流れ全体を指します。
- インスタンス生成ルールを統一できる
- 毎回似た加工処理を書く手間をなくせる
- 保守が楽になる
今回のユースケース
supabaseからデータを取得し、ユーザーのGitHub / Qiita / Xのアカウントへのリンクを画面に表示し、クリックで飛べるようにしたい
Supabaseから取れるデータ
{
"github_id": "kikowatabe",
"qiita_id": "kikowatabe",
"x_id": "kikowatabe"
}
アカウントIDしかないくURLが存在しないので、画面を作るたびにURLを毎回手書きで組み立てなければならない。
<a href={`https://github.com/${user.github_id}`}>GitHub</a>
ファクトリーメソッドの実装例
Userインスタンスを作るときにURLを持った状態にしてしまえば、簡潔にコードを書くことができます。そのためにファクトリーメソッドを使います。
static createUserFromJson(user: UserJson, skill: SkillJson): User {
//staticでインスタンスを作らずに関数を使う
//userとskillという2つのデータを引数に受け取る
return new User( // Userインスタンスを新しく作る
user.id, // Supabaseから取得したユーザーIDをそのまま渡す
user.name, // ユーザー名もそのまま渡す
user.description, // ユーザーの自己紹介文もそのまま渡す
skill.name, // ユーザーが持つスキルの名前を渡す
user.github_id ? `https://github.com/${user.github_id}` : undefined,
// GitHub IDが存在する場合だけURLに変換して渡す なければundefined
user.qiita_id ? `https://qiita.com/${user.qiita_id}` : undefined,
// Qiita IDが存在する場合だけURLに変換して渡す なければundefined
user.x_id ? `https://twitter.com/${user.x_id}` : undefined
// X(Twitter) IDが存在する場合だけURLに変換して渡す なければundefined
);
}
ポイント
- IDがあるならURLを作る
- ないならundefined
- 最初に1回だけやるので表示側がシンプルになる
データ取得後の使い方
const { data: userData } = await supabase
.from("users")
.select("*")
.eq("id", id)
.single();
const { data: skillData } = await supabase
.from("skills")
.select("*")
.eq("user_id", id)
.single();
if (userData && skillData) {
const user = User.createUserFromJson(userData, skillData);
setUser(user);
}
画面ではこうまとめられます(return内)
{user.github_url && <Link href={user.github_url} isExternal>GitHub</Link>}
{user.qiita_url && <Link href={user.qiita_url} isExternal>Qiita</Link>}
{user.x_url && <Link href={user.x_url} isExternal>X</Link>}
まとめ
- SupabaseからはIDだけが来る → URLがないと困る
- 毎回画面で組み立てたくない
- → Userを作るときにURLもセットしてしまう(ここでファクトリーメソッドを使う)
- 結果t表示側がシンプルになりミスも防げる