私は Yii フレームワーク、特にその「コンポーネント」が好きで使用しています。これらは遅延インスタンス化され、構成ファイルでスワップインまたはスワップアウトできます。依存性注入ライトのようなものです。
コードの再利用やフレームワークの変更が必要になった場合に備えて、コードのビジネス ロジックをフレームワークから完全に独立させようとしています。
サービス層に AccountService というクラスがあり、これは IAccountService を実装し、1 つの引数のコンストラクターを持っているとします。
interface IAccountService
{
function getUserById($id);
}
class AccountService implements IAccountService
{
private $_userRepository;
public function __construct(IUserRepository $userRepository) {
$this->_userRepository = $userRepository;
}
public function getUserById($id) {
return $this->_userRepository->getById($id);
}
}
偉大な。これまでのところ、完全にフレームワークフリーです。ここで、これを Yii コンポーネントとして公開したいと思います。そうすれば、遅延インスタンス化して、Yii コントローラーや他の Yii コンポーネントで簡単に使用できるようになります。
しかし、Yii コンポーネント (IApplicationComponent を実装する) は、コンストラクター引数をまったく持たない必要がありますが、私のクラスでは 1 つ必要です!
何か案は?
これが私が持っているものです。私はそれらのどれにも満足していません。どちらも過剰に設計されているように見えますが、独特のにおいがします。
オプション 1 - 作成: Yii の IApplicationComponent を実装する「AccountServiceComponent」というクラスを作成します。コンストラクターのために AccountService クラスを拡張することはできませんが、次のようにプライベート メンバーとして 1 つをインスタンス化し、そのすべてのメソッドをラップすることができます。
class AccountServiceComponent implements IApplicationComponent, IAccountservice
{
private $_accountService;
public __construct() {
$this->_accountService = new AccountService(new UserRepository());
}
public getUserById($id) {
return $this->_accountService->getUserById($id);
}
}
短所:すべてのメソッドをそのようにラップする必要があります。これは面倒であり、「バクラバ コード」につながる可能性があります。特に、それぞれに複数のメソッドを持つ複数のサービス クラスが存在することを考慮してください。
オプション 2 - mixin : (または、動作または特性、または最近呼ばれるもの。)
Yii (PHP 5.4 より前に作成されたもの) は、IBehavior を実装するクラスの形式で「振る舞い」を提供します。サービスを拡張する動作クラスを作成し、それをコンポーネントにアタッチできます。
class AccountServicesBehavior extends AccountService implements IBehavior
{
// Implement the few required methods here
}
class AccountServiceComponent implements IApplicationComponent
{
public function __construct() {
$accountService = new AccountService(new UserRepository());
$this->attachBehavior($accountService);
}
短所: 私のコンポーネントは IAccountService を公式に実装しなくなりました。また、レイヤードで過度になっているようです。
オプション 3 - オプションのコンストラクター パラメーター:
サービス クラスへのコンストラクター パラメーターをオプションにして、それをコンポーネントに拡張することができます。
class AccountService implements IAccountService
{
public $userRepository;
public function __construct(IUserRepository $userRepository = null) {
$this->userRepository = $userRepository;
}
public function getUserById($id) {
return $this->_userRepository->getById($id);
}
}
class AccountServiceComponent extends AccountService implements IApplicationComponent
{
}
短所: オプションのコンストラクター パラメーターは、必要なものすべてを提供しなくても、このクラスをインスタンス化できることを意味します。
...だから、私が見逃している他のオプションはありますか? それとも、邪魔にならないものを選ばなければならないのでしょうか?