4次元のシングルトン

Deeplからの自動翻訳

4D 20 R5は、開発者のための強力な機能を提供します:シングルトンです!

シングルトンデザインパターンは、アプリケーション全体でアクセス可能なクラスのインスタンスを1つ作成します。

このパターンには、以下のような多くの利点があります:

  • プロセス間の値のホスト
  • ユーティリティ・クラス
  • ファクトリーデザインパターンのベース
  • など多くの利点があります。

この新しいコンセプトの詳細については、このまま読み進めてください!

4Dには2種類のシングルトンがあります:プロセスごとにユニークなシングルトンと、アプリケーション全体でユニークな共有シングルトンです。シングルトンは標準オブジェクトで、共有シングルトンは共有オブジェクトです。

シングルトンを定義するのは非常に簡単で、クラスのコンストラクタにシングルトンキーワードを追加するだけです:

singleton Class constructor()

共有シングルトンの定義も非常に簡単で、共有クラスでsingletonキーワードを使うだけです:

shared singleton Class constructor()

その瞬間から、me属性を通してシングルトンに簡単にアクセスできるようになる:

$singleton:=cs.SingletonClass.me

me属性はシングルトンインスタンス(他の言語ではgetInstance()関数でアクセスすることが多い)です。シングルトンに初めてアクセスするときにインスタンス化されます。

シングルトンはとても便利なので、これからたくさん使うことになるでしょう。長い説明よりもシングルトンの例をお望みだと思いますので、いくつか用意しました。

ユーティリティ・クラス

簡単な例から始めましょう:ユーティリティクラスです。ユーティリティクラスは、アプリケーションのいたるところで使われる多くのユーティリティ関数をホストしています。これらの関数を1つのクラスにまとめると、すべてのユーティリティ関数を見つけるのがとても簡単で、メソッドが散らかることもないので、コードのメンテナンスに役立ちます。

//Class UtilityClass
 
singleton Class constructor()
 
Function utilityFunction1()
 
Function utilityFunction2()
 
...

この瞬間から、この行でユーティリティ関数を呼び出すことができます:

cs.UtilityClass.me.utilityFunction1()

Websocket サーバー・ラッパー

シングルトンのもうひとつの典型的な使い方は、アプリケーションのどこでもアクセスできるオブジェクトのラッパーを作ることです。このクラスを考えてみよう:

//WebSocketServerWrapper
 
singleton Class constructor()
 
$handler:=cs.myWebsocketServerHandler.new()
This.webSocketServer:=4D.WebSocketServer.new($handler; {dataType: “object”})
 
Function terminate()
 
This.webSocketServer.terminate()

この瞬間から、次の呼び出しによってウェブサーバーを開始することができます:

CALL WORKER(“WebSocketServerWorker”; Formula(cs.WebSocketServerWrapper.me))

を呼び出すことでウェブサーバーを起動し、

CALL WORKER(“WebSocketServerWorker”; Formula(cs.WebSocketServerWrapper.me.terminate()))

ファクトリー

3つ目の例は、ファクトリーというデザインパターンを実装しています。ファクトリーはオブジェクトの新しいインスタンスを生成します。この場合、VehicleFactoryからVehicleオブジェクトを生成します:

//Class VehicleFactory
 
property vehicleBuilt:=0 //Number of vehicles built by the factory
 
shared singleton Class constructor()
 
shared Function buildVehicle($type : Text)->$vehicle : cs.Vehicle
 
  Case of
    : $type="car"
      $vehicle:=cs.Car.new()
    : $type="truck"
      $vehicle:=cs.Truck.new()
    : $type="sport car"
      $vehicle:=cs.SportCar.new()
    : $type="motorbike"
      $vehicle:=cs.Motorbike.new()
  Else
    $vehicle:=cs.Car.new()
  End case
 
  This.vehicleBuilt+=1

シングルトンであるおかげで、このVehicleFactoryを呼び出すことで、1行でプロセス(または共有アプリケーション)のどこからでも新しいVehicleを取得することができます:

$vehicle:=cs.VehicleFactory.me.buildVehicle("truck")

その場合、このファクトリーは新しい車両を返す前にビルドされた車両の数をカウントする以外には何もしません。

VehicleFactoryをアプリケーション全体で一意にしたい場合は、sharedキーワードを追加する必要があります。関数buildVehicleは(This.vehicleBuiltをインクリメントすることで)VehicleFactoryを変更するので、関数の呼び出しと終了時にuseとend useが自動的に呼び出されるように、sharedキーワードも追加する必要があります。

プロセス間値

シングルトンのもう1つの古典的な使用法は、アプリケーション全体で使用するプロセス間値をホストすることです。このようなシングルトンの例を示します:

//Class InterprocessSingleton
 
shared singleton Class constructor()
 
This.version:=2
This.buildNumber:=1056

ここから、例えばグローバル変数にとても簡単にアクセスできます:

cs.InterprocessSingleton.me.version

ヒント: アプリケーションの起動時にプロセス間値を初期化したい場合があります。通常はOn Application Startupメソッド内で初期化します:

//Class InterprocessSingleton
 
shared singleton Class constructor($file : 4D.File)
 
$json:=$file.getText()
$settingsJson:=JSON Parse($json)
 
This.version:=$settingsJson.version
This.buildNumber:=$settingsJson.buildNumber

この場合、versionとbuildNumberの値はJSONファイルから取得します。シングルトンの場合、new()関数を呼び出すことで、コンストラクタをパラメータ付きで呼び出す方法がある。例えば、我々の場合:

$myFile:=File("/RESOURCES/settings.json")
cs.InterprocessSingleton.new($myFile)

注意しなければならないのは、new()の呼び出しがシングルトンに初めてアクセスしたときであることです。シングルトンがアクセスされた後にnew()を呼び出すと、クラスのコンストラクタは呼び出されなくなります。

特別な感謝

シングルトンにアクセスするためにme属性を追加することを提案してくれたChris Belangerに感謝の意を表したい。

シングルトンが私たちにとってそうであるように、あなたにとってもエキサイティングなものであることを願っています。シングルトンについて質問があれば、4Dフォーラムで遠慮なく質問してほしい。

Nicolas Brachfogel
- プロダクトオーナー & シニアデベロッパー - Nicolas Brachfogelは、2017年にシニアデベロッパーとして4Dに入社しました(4D Serverとネットワークを担当)。Apple Siliconのリリースを管理するプロダクトオーナーとして、ユーザーストーリーを書いて機能仕様に落とし込み、機能実装が顧客のニーズを満たしているかを確認する役割を担っています。Institut Supérieur d'Informatique Appliquée (INSIA) を卒業した Nicolas は、2001年にソフトウェア開発者としてのキャリアをスタートさせました。JavaとC++で数年間コーディングした後、ゲーム会社のクライアント・サーバー開発を専門に担当。サーバー開発者/アーキテクトとして、多くのゲーム(Dofus Arena、Drakerz、Trivial Pursuit Go!)のサーバーアーキテクチャに携わり、成功を収めてきました。