デザインパターンとは、設計でくり返し現れる問題と、その解決の形に名前を付けて整理したものです。代表的なのが、1994年に4人の著者(Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides。通称GoF=Gang of Four)がまとめた23のパターンです。

デザインパターンは23個すべてを同じ重さで覚える必要はなく、実務で出番が多いのは一部です。また、Javaのラムダ式やDIコンテナ(Springなど)の普及で、「クラスを自作しなくても、言語やフレームワークがすでに実現している」パターンも増えました。この記事では、23パターンの一覧で全体像をつかんだうえで、実務でよく使う8つについて、使いどころ・使わない場面・Java標準ライブラリやSpringでの実例を、Java 21で動かした実行結果つきで解説します。

デザインパターンの使いどころ早見表

困っていること 使うパターン Java・Springでの身近な例
アルゴリズムや方針を、状況に応じて差し替えたい Strategy Comparator、Spring Securityの PasswordEncoder
処理の流れは同じで、一部の手順だけ違う Template Method java.util.AbstractList、java.io.InputStream
引数が多いオブジェクトを、読みやすく安全に作りたい Builder HttpRequest.newBuilder()、RestClient.builder()
作るクラスの決定を、子クラスや設定に任せたい Factory Method Collection.iterator()
既存の部品のインターフェースが、こちらの期待と合わない Adapter Arrays.asList()、InputStreamReader
元のクラスを変えずに、機能を重ねて足したい Decorator BufferedInputStream、GZIPInputStream
ある出来事を、複数の処理に知らせたい Observer Springの @EventListener
インスタンスを1つだけにしたい Singleton(注意して使う) Runtime.getRuntime()、Springのシングルトンスコープ

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「デザインパターンの使いどころ|GoF23の一覧と実務でよく使う8つ」

GoF 23パターンの一覧

GoFのパターンは、目的によって生成・構造・振る舞いの3つに分類されます。「実務での出番」は、現在のJava・Spring中心の開発で、自分で設計・実装する機会の多さの目安です。

生成に関するパターン(5つ):オブジェクトの作り方

パターン ひとことで 実務での出番
Abstract Factory 関連する部品の「セット」をまとめて作る △
Builder 複雑なオブジェクトを段階的に組み立てる ◎
Factory Method 何を作るかを子クラスに決めさせる ○
Prototype 既存のオブジェクトをコピーして作る △
Singleton インスタンスを1つだけに限定する ○(多くはDIコンテナに任せる)

構造に関するパターン(7つ):クラスやオブジェクトの組み合わせ方

パターン ひとことで 実務での出番
Adapter 合わないインターフェースを変換してつなぐ ◎
Bridge 「機能の階層」と「実装の階層」を分けて、別々に増やせるようにする △
Composite 部分と全体(木構造)を同じように扱う ○
Decorator 包むことで機能を重ねて追加する ◎
Facade 複雑な仕組みに、簡単な入口を1つ用意する ○
Flyweight 同じ内容のオブジェクトを共有してメモリを節約する △(Integer のキャッシュなど標準で実現)
Proxy 代理のオブジェクトを通してアクセスを制御する ○(Springが自動で作る)

振る舞いに関するパターン(11個):処理の分担と流れ

パターン ひとことで 実務での出番
Chain of Responsibility 処理できる担当者まで、要求を順に回す ○(サーブレットのフィルターなど)
Command 命令をオブジェクトにして、保存・実行・取り消しできるようにする ○(Runnable など)
Interpreter 簡単な言語の文法をクラスで表し、解釈する △
Iterator 中身の構造を見せずに、順に取り出す ◎(拡張for文で日常的に使う)
Mediator 多数のオブジェクトのやり取りを、仲介役に集める △
Memento 状態を保存し、あとで元に戻せるようにする △(取り消し機能など)
Observer 状態の変化を、登録された相手に通知する ◎
State 状態ごとの振る舞いを、状態クラスに分ける ○
Strategy アルゴリズムを差し替え可能にする ◎
Template Method 処理の骨組みを親で決め、一部を子で実装する ○
Visitor データ構造を変えずに、新しい処理を追加する △(Java 21ではsealed+switchで代替しやすい)

全体の骨格は「生成=作り方」「構造=組み合わせ方」「振る舞い=処理の分担」と覚えると、一覧が整理しやすくなります。

実務でよく使うパターン

Strategy:方針を差し替える

Strategyは、「何をするか(アルゴリズム)」をオブジェクトとして外から渡せるようにするパターンです。Javaで最も身近な例は Comparator です。List.sort() は並べ替えの仕組みだけを持ち、「何の順に並べるか」は Comparator(戦略)として渡します。

record Item(String name, int price, int stock) {}

List<Item> items = new ArrayList<>(List.of(
    new Item("ノート", 300, 50), new Item("ペン", 120, 200), new Item("ファイル", 300, 10)));

// 並べ替えの「戦略」だけを差し替える(Comparator が Strategy)
Comparator<Item> byPrice = Comparator.comparingInt(Item::price);
Comparator<Item> byPriceThenStock = byPrice.thenComparingInt(Item::stock);

items.sort(byPrice);
System.out.println("価格順: " + items.stream().map(Item::name).toList());
items.sort(byPriceThenStock);
System.out.println("価格→在庫少ない順: " + items.stream().map(Item::name).toList());
価格順: [ペン, ノート, ファイル]
価格→在庫少ない順: [ペン, ファイル, ノート]
使いどころ 使わない場面
計算方法・並べ替え・検証ルールなどが複数あり、実行時や設定で切り替える 分岐が2つで、今後も増える予定がない(if文のほうが読みやすい)
同じ if/switch の分岐が複数の場所にある 戦略ごとの処理が1行で、ラムダ式で十分なとき(クラスを作らなくてよい)

Springでは、同じインターフェースの実装を複数Beanとして登録し、設定や条件で選ぶ形でよく使います。Spring Securityの PasswordEncoder(BCryptPasswordEncoder などを差し替える)もStrategyです。

Java 8以降は、ラムダ式がそのまま戦略になるため、インターフェースと実装クラスを毎回作る必要はありません。

Factory Method:作るものを子クラスに決めさせる

Factory Methodは、「処理の手順は親クラスが決め、その中で使うオブジェクトの生成だけを子クラスに任せる」パターンです。

// 手順(export)は親が決め、「何を作るか」(createJoiner)は子クラスが決める
abstract class Exporter {
    final String export(List<String> rows) {
        StringJoiner j = createJoiner();      // ← Factory Method
        rows.forEach(j::add);
        return j.toString();
    }
    protected abstract StringJoiner createJoiner();
}
class CsvExporter extends Exporter {
    protected StringJoiner createJoiner() { return new StringJoiner(","); }
}
class JsonExporter extends Exporter {
    protected StringJoiner createJoiner() { return new StringJoiner("\",\"", "[\"", "\"]"); }
}

for (Exporter e : List.of(new CsvExporter(), new JsonExporter())) {
    System.out.println(e.export(List.of("a", "b")));
}
a,b
["a","b"]

Java標準では、Collection.iterator() が代表例です。ArrayList と HashSet はそれぞれ自分に合ったIteratorを作り、使う側は具体的なクラスを知りません。

混同しやすい点として、List.of() や Integer.valueOf() のような「staticファクトリメソッド」は、GoFのFactory Methodとは別物です。staticファクトリメソッドは「コンストラクターの代わりに、名前の付いたstaticメソッドで生成する」という書き方(書籍『Effective Java』で推奨)で、子クラスに生成を任せる仕組みではありません。

使いどころ 使わない場面
フレームワークやライブラリを作り、生成するものを利用者に拡張させたい 生成するクラスが1つだけ(new で十分)
手順は共通で、使う部品だけが種類ごとに違う DIコンテナで実装を差し替えられる場合(Springでは設定で選ぶほうが簡単)

Builder:引数の多いオブジェクトを安全に組み立てる

Builderは、オブジェクトの組み立てを段階的に行い、最後に build() で完成させるパターンです。引数が多いコンストラクター(new Report("月次", 30, true, false, null, …))は、どの値が何の意味かを読み取れず、順番の間違いにも気づきにくいという問題があります。

// 自作の Builder:必須項目と任意項目を分け、build() でまとめてチェック
record Report(String title, int pageSize, boolean landscape) {
    static class Builder {
        private final String title;
        private int pageSize = 50;
        private boolean landscape = false;
        Builder(String title) { this.title = title; }
        Builder pageSize(int v) { this.pageSize = v; return this; }
        Builder landscape(boolean v) { this.landscape = v; return this; }
        Report build() {
            if (title.isBlank()) throw new IllegalStateException("title は必須です");
            return new Report(title, pageSize, landscape);
        }
    }
}
Report r = new Report.Builder("月次レポート").pageSize(30).landscape(true).build();
System.out.println(r);
try {
    new Report.Builder("").build();
} catch (IllegalStateException e) {
    System.out.println("エラー: " + e.getMessage());
}
Report[title=月次レポート, pageSize=30, landscape=true]
エラー: title は必須です

必須項目はBuilderのコンストラクターで受け取り、任意項目はメソッドで設定し、build() で整合性をまとめてチェックするのが基本の形です。完成したオブジェクトは変更できない(イミュータブル)ようにします。

使いどころ 使わない場面
任意の項目が多い(目安として4〜5個以上) 項目が2〜3個なら、recordのコンストラクターで十分
組み立ての途中は不完全でよく、完成時にまとめて検証したい すべての項目が必須で、順番の取り違えが起きにくい

Java標準では HttpRequest.newBuilder(uri).timeout(...).header(...).POST(...).build()、Springでは RestClient.builder() や WebClient.builder() など、設定項目の多いクラスの多くがBuilderを提供しています。

Adapter:合わない形を変換してつなぐ

Adapterは、既存の部品のインターフェースを、こちらが期待する形に変換する「変換プラグ」のようなパターンです。変更できない既存コードや外部ライブラリを、自分のシステムに組み込むときに使います。

interface Temperature { double celsius(); }        // こちらのシステムが期待する形

class LegacySensor {                                // 変更できない既存の部品(華氏を返す)
    double readFahrenheit() { return 77.0; }
}
class FahrenheitAdapter implements Temperature {    // 形を合わせる変換役
    private final LegacySensor sensor;
    FahrenheitAdapter(LegacySensor sensor) { this.sensor = sensor; }
    public double celsius() { return (sensor.readFahrenheit() - 32) * 5 / 9; }
}

// Java標準:配列を List として扱う Adapter(元の配列と連動する)
String[] arr = {"a", "b", "c"};
List<String> view = Arrays.asList(arr);
view.set(0, "z");
System.out.println("配列も変わる: " + Arrays.toString(arr));
try { view.add("d"); } catch (UnsupportedOperationException e) { System.out.println("add は不可: " + e); }
現在の気温: 25.0℃
配列も変わる: [z, b, c]
add は不可: java.lang.UnsupportedOperationException

Arrays.asList() は配列をListの形で見せる変換役なので、set は元の配列に反映され、要素数を変える add はできません。Adapterは「形を変えるだけで、中身は元のまま」という性質がよくわかる例です。バイト列を文字として読む InputStreamReader もAdapterです。

使いどころ 使わない場面
外部ライブラリや既存システムの形を、自分のコードに持ち込まないようにしたい 自分で変更できるコード同士(インターフェース自体を直すほうが簡単)
ライブラリを将来差し替える可能性がある 変換が1か所だけで、今後も増えない

Spring MVCの内部では、HandlerAdapter が、形の違うさまざまなハンドラー(コントローラー)を共通の方法で呼び出すために使われています。

Decorator:包んで機能を重ねる

Decoratorは、同じインターフェースを持つオブジェクトで「包む」ことで、元のクラスを変えずに機能を追加するパターンです。Java標準の入出力(java.io)が代表例で、new BufferedReader(new InputStreamReader(new GZIPInputStream(in), UTF_8)) のように、「展開する」「文字に変換する」「行単位で読む」機能を包んで重ねていきます。

// 自作:同じインターフェースを持つ部品で包み、処理を足す
interface Notifier { void send(String msg); }
class Chat implements Notifier {
    public void send(String msg) { System.out.println("  [チャット] " + msg); }
}
class Logging implements Notifier {
    private final Notifier inner;
    Logging(Notifier inner) { this.inner = inner; }
    public void send(String msg) { System.out.println("  log: 送信開始"); inner.send(msg); System.out.println("  log: 送信終了"); }
}
Notifier n = new Retry(new Logging(new Chat()), 2);   // Retry(失敗時に再送)も同じ形の Decorator。定義は省略
n.send("デプロイ完了");
  log: 送信開始
  [チャット] デプロイ完了
  log: 送信終了

ログ、リトライ、キャッシュ、計測のような「本来の処理の前後に足したいもの」を、組み合わせ自由な部品にできるのが強みです。継承で LoggingRetryChat のようなクラスを組み合わせの数だけ作る必要がなくなります。

使いどころ 使わない場面
追加したい機能が複数あり、組み合わせを自由に変えたい 追加する機能が1つだけで固定
元のクラスを変更できない、または変更したくない 包む層が深くなりすぎて、処理の流れを追えなくなる

Springでは、トランザクションやキャッシュのような「前後に足す処理」は、Decoratorを自作するより、AOP(@Transactional、@Cacheable)に任せるのが一般的です。これはSpringが自動で作るProxyの仕組みです(後述)。

Observer:出来事を複数の相手に知らせる

Observerは、ある出来事(イベント)が起きたとき、登録されている相手(リスナー)にまとめて通知するパターンです。通知する側は、誰が聞いているかを知らなくてよいのがポイントです。

class OrderEvents {
    private final List<Consumer<String>> listeners = new ArrayList<>();
    void subscribe(Consumer<String> l) { listeners.add(l); }
    void placed(String orderId) { listeners.forEach(l -> l.accept(orderId)); }
}

var order = new OrderEvents();
order.subscribe(id -> System.out.println("在庫: 注文 " + id + " の在庫を引き当て"));
order.subscribe(id -> System.out.println("メール: 注文 " + id + " の確認メールを送信"));
order.subscribe(id -> System.out.println("ポイント: 注文 " + id + " にポイント付与"));
order.placed("A-001");   // 注文側は、誰が聞いているかを知らない
在庫: 注文 A-001 の在庫を引き当て
メール: 注文 A-001 の確認メールを送信
ポイント: 注文 A-001 にポイント付与

「注文後にポイントも付けたい」という変更は、リスナーを1つ追加するだけで済み、注文の処理は変わりません。

Java標準の java.util.Observable と Observer は、Java 9で非推奨(deprecated)になっています。実際にコンパイルすると、次の警告が出ます。

ObservableDemo.java:3: warning: [deprecation] Observable in java.util has been deprecated

現在は、自分でリスナーのリストを持つ(上の例)、Springの ApplicationEventPublisher と @EventListener、非同期のデータの流れなら java.util.concurrent.Flow などを使います。

使いどころ 使わない場面
1つの出来事に、独立した後続処理が複数ある 処理の順番や、すべて成功したかどうかが重要(明示的に順に呼ぶほうが安全)
後続処理が今後も増えそう 通知先が1つだけ

通知の流れはコードから追いにくくなるため、「どのイベントを、誰が受け取っているか」を一覧で把握できるようにしておくと、保守しやすくなります。

Template Method:処理の骨組みを固定する

Template Methodは、処理の流れ(骨組み)を親クラスで決め、一部の手順だけを子クラスで実装するパターンです。

abstract class ImportJob {
    // 処理の流れ(テンプレート)は親が固定する。final で上書きを防ぐ
    final void run(List<String> lines) {
        int ok = 0;
        for (String line : skipHeader(lines)) {
            if (!valid(line)) { System.out.println("スキップ: '" + line + "'"); continue; }
            save(parse(line)); ok++;
        }
        System.out.println("取り込み件数: " + ok);
    }
    protected List<String> skipHeader(List<String> lines) { return lines.subList(1, lines.size()); } // 既定の動き(フック)
    protected boolean valid(String line) { return !line.isBlank(); }
    protected abstract String[] parse(String line);   // 子クラスが決める部分
    protected abstract void save(String[] cols);
}
class CsvImport extends ImportJob {
    protected String[] parse(String line) { return line.split(","); }
    protected void save(String[] c) { System.out.println("保存: id=" + c[0] + " name=" + c[1]); }
}

new CsvImport().run(List.of("id,name", "1,ノート", "", "2,ペン"));
保存: id=1 name=ノート
スキップ: ''
保存: id=2 name=ペン
取り込み件数: 2

Java標準では、AbstractList(get と size だけ実装すれば、残りのメソッドが使える)や、InputStream(1バイト読む read() を実装すれば、配列に読む read(byte[]) が使える)がこの形です。

Springの JdbcTemplate は名前に「Template」とありますが、継承ではなく、処理の一部(RowMapper など)をコールバックとして渡す形です。同じ「骨組みは固定、一部だけ差し替え」を、継承の代わりにStrategy(渡す)で実現しています。現在は、継承より、このコールバック方式のほうが柔軟で、よく選ばれます。

使いどころ 使わない場面
手順の順番を必ず守らせたい(前処理→本処理→後処理) 子クラスごとの違いが大きく、骨組みを共有できない
種類ごとの違いが、一部の手順に限られる 継承の階層が深くなる(コールバックで渡す形を検討)

Singleton:使う前に注意したいパターン

Singletonは、あるクラスのインスタンスが1つだけであることを保証するパターンです。Java標準では Runtime.getRuntime() が代表例です。Javaで自作する場合は、enum で書くのが最も安全(シリアライズやリフレクションでも2つ目が作られない)とされています。

一方で、状態を持つSingletonは、プログラム全体から触れる「グローバル変数」と同じ性質を持ちます。テストが互いに影響し合う例を見てみます。

enum Counter {                                        // enum で書くのが最も安全な Singleton
    INSTANCE;
    private int count;
    void increment() { count++; }
    int value() { return count; }
}

System.out.println("Runtime は同じ? " + (Runtime.getRuntime() == Runtime.getRuntime()));
Counter.INSTANCE.increment();                 // テストA
System.out.println("テストAの後: " + Counter.INSTANCE.value());
Counter.INSTANCE.increment();                 // テストB(1 を期待しているが…)
System.out.println("テストBの後: " + Counter.INSTANCE.value() + "(テストBは 1 を期待)");
Runtime は同じ? true
テストAの後: 1
テストBの後: 2(テストBは 1 を期待)

テストの実行順によって結果が変わり、テスト用の偽物にも差し替えられません。

Spring Bootでは、Beanは標準で「シングルトンスコープ」(1つのコンテナにつき1つ)です。ただしこれはGoFのSingletonとは違い、クラス自身は普通のクラスのままで、コンテナが1つだけ作って配ってくれます。テストでは別のインスタンスや偽物を渡せるため、「1つだけにしたい」ならDIコンテナに任せるのが現在の定番です。なお、シングルトンのBeanは複数のリクエストから同時に使われるため、リクエストごとの値をフィールドに持たないようにします。

Springが自動で使っているパターン

自分でクラスを書かなくても、Springを使うだけで多くのパターンに触れています。仕組みを知っておくと、よくあるつまずきの原因がわかります。

パターン Springでの例 知っておくと役立つこと
Proxy @Transactional、@Cacheable、@Async 同じクラスの中からメソッドを呼ぶと、プロキシを通らないため効かない
Singleton(スコープ) Beanの標準スコープ フィールドにリクエストごとの状態を持たない
Factory BeanFactory、FactoryBean Beanの生成はコンテナが担当する
Observer ApplicationEventPublisher、@EventListener 標準は同期実行。非同期にするには @Async などが必要
Chain of Responsibility Spring Securityの SecurityFilterChain、サーブレットの FilterChain フィルターの順番が動作を左右する
Adapter Spring MVCの HandlerAdapter 形の違うハンドラーを共通の方法で呼び出す
Strategy PasswordEncoder など多くのインターフェース 実装を差し替えるだけで振る舞いを変えられる

モダンJavaで変わった書き方

GoFの本は1994年の出版で、当時のC++とSmalltalkを前提にしています。パターンの考え方は今も有効ですが、書き方は言語の進化で簡単になりました。

パターン 昔の書き方 現在のJavaでの書き方
Strategy / Command インターフェース+実装クラスを毎回作る ラムダ式やメソッド参照を渡す
Observer java.util.Observable を継承 リスナーのリスト+ラムダ式、Springのイベント
Singleton private static のインスタンス+同期処理 enum、またはDIコンテナのスコープ
Visitor accept / visit の二重の呼び出し sealedインターフェース+switchのパターンマッチング(Java 21)
Flyweight 共有プールを自作 Integer.valueOf() などが標準で実現
Iterator 自作のIteratorクラス 拡張for文、Stream API

たとえばFlyweightは、Integer のキャッシュとしてJava標準に入っています(Java 21で確認すると、Integer の 127 == 127 は true、128 == 128 は false)。Integer.valueOf() は、標準の設定で-128〜127の値を共有します。ラッパー型の比較に == を使うと、値によって結果が変わるため、比較には equals を使います。

デザインパターンを使うときの注意

よくある失敗 起きること こうするとよい
パターンを使うこと自体が目的になる 小さな処理に、クラスが何個も増える 困りごとが先、パターンは後。早見表の「困っていること」から選ぶ
将来の変更を想像して、先に抽象化する 実際には変更されず、読みにくさだけが残る 同じ変更が2〜3回起きてから導入する
名前だけパターンにする(XxxFactory の中身がただの new) 読む人が構造を誤解する パターン名をクラス名に付けるのは、本当にその形のときだけ
Singletonで共有の状態を持つ テストが不安定になり、並行処理で値が混ざる 状態を持たない、またはDIコンテナのスコープに任せる

デザインパターンの一番の価値は「共通の語彙」になることです。レビューで「ここはStrategyにしましょう」と言えば、クラスの形まで一言で伝わります。

よくある質問

Q. 23パターンをすべて覚える必要はありますか? A. ありません。まずはStrategy、Template Method、Builder、Adapter、Decorator、Observerの6つと、Singletonの注意点を押さえれば、実務のコードの多くが読めるようになります。残りは、一覧表で「こういう問題にはこういう形がある」と知っておき、必要になったときに調べれば十分です。

Q. StrategyとTemplate Methodの違いは何ですか? A. どちらも「一部を差し替える」パターンですが、Strategyは部品を外から渡す(組み合わせ)、Template Methodは子クラスで上書きする(継承)という違いがあります。実行時に切り替えたい、組み合わせを増やしたい場合はStrategyが向いています。

Q. DecoratorとProxyの違いは何ですか? A. 形(同じインターフェースで包む)はよく似ています。Decoratorは「機能を追加する」ことが目的で、何重にも重ねて使います。Proxyは「アクセスを制御する」ことが目的で、遅延読み込み、権限チェック、トランザクションの開始などを代理で行います。

まとめ

  • デザインパターンは、設計でくり返し現れる問題と解決の形に付けた名前。GoFの23パターンは生成・構造・振る舞いの3分類
  • 実務でよく使うのはStrategy、Builder、Adapter、Decorator、Observer、Template Methodなど一部
  • Comparator=Strategy、java.io=Decorator、Arrays.asList=Adapterのように、Java標準ライブラリはパターンの実例の宝庫
  • Singletonは状態を持つとテストが不安定になる。「1つだけ」はDIコンテナのスコープに任せる
  • Springの @Transactional はProxy。同じクラス内からの呼び出しでは効かない
  • ラムダ式・enum・sealed+switchで、モダンJavaではパターンの書き方が簡単になった
  • 困りごとが先、パターンは後。変更が実際に起きてから導入する

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「デザインパターンの使いどころ|GoF23の一覧と実務でよく使う8つ」

株式会社RJCでは、読みやすく変更しやすいコードを目指して、設計の引き出しをプロジェクトの中で仲間と増やしています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?