デザインパターン:抽象ファクトリとファクトリメソッド


141

注:質問は投稿の最後にあります。

Abstract FactoryとFactory Methodに関する他のスタックオーバーフロースレッドを読みました。各パターンの意図を理解しています。しかし、私はその定義を明確にしていません。

Factoryメソッドは、オブジェクトを作成するためのインターフェースを定義しますが、インスタンス化するものをサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに遅らせることができます。

対照的に、抽象ファクトリは、具体的なクラスを指定せずに、関連するオブジェクトまたは依存するオブジェクトのファミリを作成するためのインターフェースを提供します。

- ジョン・フェミネラ

抽象ファクトリーと非常によく似ていますファクトリメソッド。私のポイントを説明するために、いくつかのUMLクラスを描画しました。

注意:

  • 図はwww.yuml.comからのものですので、完全に方向付けられていません。しかし、それは無料のサービスです:)。
  • 図は完全ではない場合があります。GoFのデザインパターンはまだ学習中です。

工場での方法:

ファクトリーメソッド

抽象ファクトリー(1メンバーのみ):

抽象ファクトリー(1メンバーのみ)

抽象ファクトリー(より多くのメンバー):

代替テキスト

質問:

  1. 場合抽象工場は一つだけ作成者と一つの製品を持っている、それはまだある、抽象ファクトリパターン?(家族を作成するためのインターフェース)
  2. ファクトリメソッドコンクリートクリエーターをインターフェイスから作成できますか、それともクラスから作成する必要がありますか?(クラスはインスタンス化をサブクラスに延期します)
  3. 抽象工場は一つだけ作成者と一つの製品を持つことができる場合は、唯一の違いである抽象工場ファクトリメソッド元のための作成者が、後者はクラスであるためにインターフェイスと作成者であることは?

1
注:インターフェースについて言及するとき、私はJavaインターフェース(抽象仮想メソッドを持つ抽象クラス)の観点からさらに考えていました。異なる言語でAbstract FactoryとFactoryメソッドの間に違いがあるかどうかを明確にしてください。

ここでの基本的な違い:stackoverflow.com/questions/1001767、ただしあなたが求めているほど具体的ではありません...
nawfal

回答:


134

お役に立てれば。さまざまなタイプの工場について説明します。参照としてヘッドファーストデザインパターンを使用しました。図にはyuml.meを使用しました。

静的ファクトリー

Productのさまざまなサブタイプを生成するための静的メソッドを持つクラスです。

静的ファクトリー

シンプルファクトリー

Productのさまざまなサブタイプを作成できるクラスです。(スタティックファクトリよりも優れています。新しいタイプが追加された場合、基本のProductクラスを変更する必要はなく、シンプルファクトリクラスのみです)

シンプルファクトリー

ファクトリーメソッド

そのタイプに関連する1つのタイプの製品を生成する1つのメソッドが含まれています。(タイプはサブクラスに委譲されるため、Simple Factoryよりも優れています。)

ファクトリーメソッド

抽象ファクトリー

関連するタイプのファミリーを生成します。生成する型のメソッドが複数あるため、ファクトリメソッドとは著しく異なります。(これは複雑です。実際の例については、次の図を参照してください)。

抽象ファクトリー

.NET Frameworkの例

DbFactoriesProviderにはサブタイプがないため、シンプルファクトリです。DbFactoryProviderは、接続やコマンドオブジェクトなどのさまざまな関連データベースオブジェクトを作成できるため、抽象ファクトリです。

.NET Frameworkからの抽象ファクトリ


Static FactoryとSimple Factoryの違いは、純粋にCreateProductメソッドが別のクラス内にあるということですか?
Peter O'Callaghan

4
ファクトリー・メソッドの場合、Product(抽象として)、そして、Product1そしてProduct2息子として存在した場合、それはより明確ではないでしょうか?これは、ファクトリーメソッドが1つの製品を作成することに関するものであるのに対し、抽象ファクトリーは、多かれ少なかれ、ファクトリーメソッドの集まりであり、ファミリーにまとめられています。
lllllll 2013

79

2つのパターンは確かに関連しています!

パターン間の違いは、一般的に意図されています。

目的ファクトリメソッド「オブジェクトを作成するためのインターフェイスを定義しますが、サブクラスがファクトリメソッドは、サブクラスにクラス延期のインスタンスをインスタンス化することができますどのクラス。決めましょう。」です

意思抽象工場は、「彼らの具象クラスを指定せずに、関連または依存オブジェクトの家族を作成するためのインタフェースを提供します。」であります

これらのインテントステートメント(GoFから引用)に純粋に基づいて、確かにファクトリーメソッドは、ある意味で、ファミリーのある「縮退した」抽象ファクトリーであると言えます。

FactoryメソッドAbstract Factoryよりもかなりシンプルなので、一般的に実装が異なる傾向があります。

ただし、それらは実装においても関連しています。GoF本で述べたように、

AbstractFactoryは、製品を作成するためのインターフェースのみを宣言します。それらを実際に作成するのは、ConcreteProductサブクラス次第です。これを行う最も一般的な方法は、各製品のファクトリメソッドを定義することです。

このc2 wikiにも、このトピックに関する興味深い議論があります。


7
コメントも投票もわかりません。詳しく説明できますか?
Don Roby

まあ、答えは修辞私には思わない...いいえ、実際の具象例...広すぎる...
ノヴァーリス

14

OPの(優れた)質問のリストは無視されているようです。現在の回答は、再ハッシュされた定義を提供するだけです。したがって、私は元の質問に簡潔に対処しようとします。

  1. 場合抽象工場は一つだけ作成者と一つの製品を持っている、それはまだある、抽象ファクトリパターン?(家族を作成するためのインターフェース)

いいえ。抽象ファクトリー、「関連製品のファミリー」を作成するために複数の製品を作成する必要があります。標準的なGoFの例ではScrollBar()、およびを作成しWindow()ます。利点(および目的)は、抽象ファクトリーが複数の製品に共通のテーマを適用できることです。

  1. ファクトリメソッドコンクリートクリエーターをインターフェイスから作成できますか、それともクラスから作成する必要がありますか?(クラスはインスタンス化をサブクラスに延期します)

まず、GoFが本を書いたとき、JavaもC#も存在しなかったことに注意する必要があります。GoFでのインターフェースという用語の使用は、特定の言語によって導入されたインターフェースタイプとは無関係です。したがって、具象クリエーターは任意のAPIから作成できます。パターンの重要な点は、APIが独自のファクトリメソッドを使用することです。そのため、メソッドが1つしかないインターフェースは、抽象ファクトリになる以上のファクトリメソッドにはなれません。

  1. 抽象工場は一つだけ作成者と一つの製品を持つことができる場合は、唯一の違いである抽象工場ファクトリメソッド元のための作成者が、後者はクラスであるためにインターフェイスと作成者であることは?

上記の回答に従って、この質問は無効になりました。ただし、抽象ファクトリーとファクトリーメソッドの唯一の違いは作成された製品の数であると考えている場合は、クライアントがこれらの各パターンをどのように消費するかを検討してください。抽象ファクトリは通常、クライアントに挿入され、構成/委任を介して呼び出されます。ファクトリメソッドは継承する必要があります。したがって、すべては古い構成と継承の議論に戻ります。

しかし、これらの答えは4番目の質問を引き起こしました!

  1. 以来、唯一の方法とのインターフェイスにすることはできませんファクトリメソッドに任意のより多くのそれができるよりも抽象工場我々は唯一の方法で生成に関するインターフェースを呼び出す何をすべきか?

メソッドが静的である場合、それは一般にStatic Factoryと呼ばれます。メソッドが静的でない場合、それは一般にSimple Factoryと呼ばれます。これらはどちらもGoFパターンではありませんが、実際にははるかに一般的に使用されています!


1
合成と継承について、私はいつも疑問に思いました。ファクトリメソッドパターンを使用して合成を行うことはできないのでしょうか。適切なコンクリート工場をクライアントに構成または注入することを妨げるものは何ですか?それとも、これはすでにパターンの範囲外のものですか?
georaldc 2017

1
@ georaldc、GoFから(107ページ)「ファクトリーメソッドは、クラスがインスタンス化をサブクラスに延期できるようにします。」つまり、ファクトリーメソッドは、定義により継承を使用します。
jaco0646 2017

4

私の意見では、2つのパターンのわずかな違いは適用可能性にあり、すでに述べたように、意図にもあります。

定義を要約しましょう(両方ともWikipediaから)。

抽象ファクトリー

具体的クラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリ作成するためのインターフェースを提供します。

ファクトリーメソッド

オブジェクトを作成するためインターフェースを定義しますがインターフェースを実装するクラスにインスタンス化するクラスを決定さます。Factoryメソッドを使用すると、クラスはインスタンス化をサブクラスに遅らせることができます。

どちらのパターンでも、ユーザーオブジェクトを必要なインスタンスの作成(実行時の分離)から分離することができます。これが一般的な側面です。どちらのパターンでも、特定のニーズに応じてファクトリの階層を作成できます。これは、もう1つの共通の側面です。

Abstract Factoryを使用すると、1つのサブクラスで複数の異なるタイプのインスタンスを作成し、その異なるサブクラスでの作成動作を特定化できます。通常、Factoryメソッドは、サブクラス化メカニズムに従って特定化できるオブジェクトの1つのタイプのみの作成を宣言します。それが違いです。

要約することによって。Productが作成オブジェクトのスーパークラスを定義し、ProductAとProductBが2つの異なるサブクラスであるとしましょう。したがって、Abstract Factoryメソッドには、createProductA()とcreateProductB()という2つのメソッドがあり、これらは特定のサブクラスで(作成ステップの観点から)特殊化されます。ファクトリサブクラスは、2つの定義済みクラスの作成ステップを特定化します。作成中のオブジェクトの。

上記の例によると、ファクトリメソッドは異なる方法で実装され、同じ数のファクトリでProductAとProductBの作成を抽象化します(ファクトリごとに1つのメソッド)。作成ステップのさらなる特殊化は、構築時に階層に委任されます。 。


2

オブジェクトを作成するメソッドが1つだけのオブジェクトを作成する抽象化された(インターフェイスまたは抽象基本クラスを介して参照されるファクトリークラスを作成した場合、それはFactoryメソッドになります。

抽象化されたFactoryにオブジェクトを作成するメソッドが複数ある場合、それはAbstract Factoryになります。

MVCコントローラーのアクションメソッドのニーズを処理するマネージャーを作成するとします。ビューモデルの作成に使用されるエンジンオブジェクトの作成など、1つのメソッドがある場合、それはファクトリメソッドパターンになります。一方、ビューモデルエンジンを作成するメソッドとアクションモデルエンジンを作成するメソッド(またはアクションメソッドにコンシューマが含まれるモデルを呼び出すもの)の2つのメソッドがある場合、それは抽象ファクトリになります。

public ActionResult DoSomething(SpecificActionModel model)
{
    var actionModelEngine = manager.GetActionModelEngine<SpecificActionModel>();
    actionModelEngine.Execute(SpecificActionModelEnum.Value);

    var viewModelEngine = manager.GetViewModelEngine<SpecificViewModel>();
    return View(viewModelEngine.GetViewModel(SpecificViewModelEnum.Value);
}

1

StackOverflowの人たちが他の投稿でも同様にこの問題について質問してから長い年月が経ちましたが(最も古いのは2009年までです)、私はまだ私が望んでいた答えを見つけることができませんでした。


だから私はウェブで数時間研究し、例を見直し、この結論に達しました、ファクトリーメソッドとアブストラクトファクトリーの主な違いは

  • 意図:一貫性または「ルックアンドフィール」:Abstract Factoryの意図は、同じスタイルのオブジェクトのファミリーをグループ化することです(たとえば、同じルックアンドフィールのUIウィジェット、同じスタイルの車のパーツ、同じOSのオブジェクト、など)Abstract Factoryの多くの例では、「同じルックアンドフィール」というキーフレーズについて言及しています。
  • より大きなグループオブジェクトを形成するオブジェクト:Abstract Factoryは、単一のオブジェクトではなく、より大きなグループオブジェクトを形成するオブジェクトのファミリを作成します。
  • 後で新しいスタイルを追加する:ファクトリメソッドを使い続けて、新しいスタイルのセットを既存のインフラストラクチャに追加しようとすると、苦痛です。抽象ファクトリーでは、抽象ファクトリークラスを実装する新しい具象ファクトリーを作成するだけです。

反例は

  • セダンに使用されるスポーツカー用の自動車部品。この不一致は事故につながる可能性があります。
  • さまざまなOS GUIウィジェットのWindowsスタイルのボタン。それは何も壊すつもりはありませんが、私のような一部の人々のユーザーエクスペリエンスを損ないます。
  • 後で、ソフトウェアを下位互換性を維持しながら、互換性のあるシステムオブジェクトの異なるセットを必要とする次のOSアップグレードでソフトウェアを実行する必要があることがわかりました。

したがって、最終的なオブジェクトグループがオブジェクトの例外なく同じスタイル持つ必要があり、この「同じスタイルを維持する」詳細を非表示にする場合は、抽象ファクトリを使用する必要があります。


0

抽象ファクトリーとファクトリーメソッドの定義の意味を理解している限り、最初の定義は静的コンテキストで実装され、入力パラメーターに基づいてオブジェクトを提供します。

2つ目は、ファクトリメソッドインターフェースを実装する、すでに作成されているオブジェクト(ファミリ)を使用します。次に、ファクトリメソッドは、元のオブジェクトに関係なく特定のインスタンスを作成します。

したがって、通常、これは両方のパターンを一緒に使用することにつながり、最初のステップで、関連するオブジェクトのファミリを説明する一般的なオブジェクトを作成します。静的メソッドgetInstance( "my family name")メソッドによって呼び出されます。そのようなgetInstanceメソッドの実装は、どのファミリオブジェクトを作成するかを決定します。

次に、新しく作成されたファミリーオブジェクトでcreateProduct()メソッドを呼び出します。ファミリーオブジェクトによっては、新しい製品が返されます。

これらのパターンはそれぞれに連携しているようです。

つまり、抽象ファクトリは「WHAT」が作成され、ファクトリメソッド「HOW」が作成されることに焦点を当てています。


0

覚えておく必要があるのは、抽象ファクトリは複数のファクトリを返すことができるファクトリであることです。したがって、AnimalSpeciesFactoryがある場合は、次のようなファクトリを返すことができます。

Mamalfactory、BirdFactory、Fishfactory、ReptileFactory。これで、AnimalSpeciesFactoryから単一のファクトリーが作成されたので、ファクトリーパターンを使用して特定のオブジェクトを作成します。たとえば、このAnimalFactoryからReptileFactoryを取得し、ヘビ、カメ、トカゲなどの爬虫類オブジェクトを作成するとします。


0
/*
//Factory methods:

//1. Factory Method - Abstract Creator Class



#include <iostream>
#include <string.h>
using namespace std;

const std::string nineNintyCC = std::string("990CC");
const std::string thousandTwoHundredCC = std::string("1200CC");
const std::string ThousandFiveHundredCC = std::string("1500CC");
const std::string fiveThousandCC = std::string("5000CC");

// Product
class Engine
{
    public:
    virtual void packEngine() = 0;  
};

// Concrete products
// concrete product class one
class C990CCEngine: public Engine
{

    public:
    void packEngine()
    {
       cout << "Pack 990CC engine" << endl;   
    }
};

// concrete class Two
class C1200CCEngine: public Engine
{   public:
    void packEngine()
    {
        cout << "pack 1200CC engine" << endl;
    }

};

// Concrete class Three
class C1500CCEngine: public Engine
{
    public:
    void packEngine()
    {
        cout << "Pack 1500CC engine" << endl;
    }

};


// Car Factory:
class CarFactory{
    public:

    virtual Engine* createEngine(const std::string& type) = 0;
};
class Factory: public CarFactory
{
    public:
     Engine *createEngine(const std::string& type)
     {

          if(0 == nineNintyCC.compare(type))
          {    
             return new C990CCEngine;
          }
          else if(0 == thousandTwoHundredCC.compare(type))
          {
             return new C1200CCEngine;
          }
          else if(0 == ThousandFiveHundredCC.compare(type))
          {
             return new C1500CCEngine;
          } 
          else
           {
                 cout << "Invalid factory input" << endl;
             return NULL;
           }
           return NULL;
     }
};

int main()
{

    CarFactory* ptr = new Factory;
    Engine*pEngine =  ptr->createEngine(nineNintyCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(ThousandFiveHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(thousandTwoHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine = ptr-> createEngine(fiveThousandCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    return 0;
}

*/
/*
//
// interface product
#include <iostream>
#include <string>
using namespace std;

class Engine
{
 public:
 virtual void EngineType() = 0;

};

// concrte product
class AltoEngine: public Engine
{
  public:
  void EngineType()
  {
      cout << "Alto Engine" << endl;
  }
};

//Concrte product
class SwiftEngine : public Engine
{
    public:
    void EngineType()
    {
        cout << "Swift Engine" << endl;    
    }
};

class Body
{
   public:
    virtual void bodyType() = 0;

};

class AltoBody: public Body
{
  public:  
    virtual void bodyType()
    {
        cout << "Alto Car Body" << endl;
    }
};

class SwiftBody : public Body
{
    public:
    void bodyType()
    {
        cout << "SwiftCar Body" << endl;
    }

};


class CarFactory
{
   public:
   virtual Engine* createEngineProduct() = 0;
   virtual Body*   createBodyPoduct() = 0;
};
class AltoCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new AltoEngine;
    }
    Body* createBodyPoduct()
    {
        return new AltoBody;
    }

};

class SwiftCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new SwiftEngine;
    }
    Body* createBodyPoduct()
    {
        return new SwiftBody;
    }

};

int main()
{

    CarFactory* pAltoFactory = new AltoCarFactory;
    Engine* pAltoEngine = pAltoFactory->createEngineProduct();
    pAltoEngine->EngineType();
    Body* pAltoBody = pAltoFactory->createBodyPoduct();
    pAltoBody->bodyType();



    CarFactory* pSwiftFactory = NULL;
    pSwiftFactory = new SwiftCarFactory;
    Engine* pSwiftEngine = pSwiftFactory->createEngineProduct();
    pSwiftEngine->EngineType();
    Body* pSwfitBody = pSwiftFactory->createBodyPoduct();
    pSwfitBody->bodyType();
    delete pAltoBody;
    delete pAltoFactory;
    delete pSwfitBody;
    delete pSwiftFactory;
    return 0;
}
*/

/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");
// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Engine Engine" << endl;
  }

};
// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Engine" << endl;
    }

};
// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Engine" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createFactory(const std::string&) = 0;
};

// EngineFactory
class CarEngineFactory : public CarFactory
{
     public:
     CarEngine* createFactory(const std::string&  type)
     {
          if(0 == maruthi.compare(type))
          {
              return new MaruthiEngine;

          }
          else if(0 == fiat.compare(type))
          {
              return  new FiatEngine;
          }
          else if(0 == renault.compare(type))
          {
              return new RenaultEngine;
          }
          else
          {
              cout << "Invalid Engine type" << endl;
              return NULL;
          }
     }

  };

int main()
{
    CarFactory* pCarFactory = new CarEngineFactory;
    CarEngine* pMaruthiCarEngine = pCarFactory->createFactory(maruthi);
    pMaruthiCarEngine->engineType();

    CarEngine* pFiatCarEngine = pCarFactory->createFactory(fiat);
    pFiatCarEngine->engineType();


    CarEngine* pRenaultCarEngine = pCarFactory->createFactory(renault);
    pRenaultCarEngine->engineType();

    return 0;
}


*/


/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");


// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Car Engine" << endl;
  }

};

// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Car Engine" << endl;
    }

};

// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Car Engine" << endl;
    }
};

// Interface
class CarBody
{
 public:
    virtual void bodyType() = 0;
};

// Concrete class
class FiatBody: public CarBody
{
  public:
  void bodyType()
  {
      cout << "Fait car Body" << endl;
  }

};

// ConcreteClass
class RenaultBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Renault Body" << endl;
    }

};

// Concrete class
class MaruthiBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Maruthi body" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createCarEngineProduct() = 0;
    virtual CarBody* createCarBodyProduct() = 0;
};

// FiatFactory
class FaitCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
        return new FiatEngine; 
     }
     CarBody* createCarBodyProduct()
     {
         return new FiatBody;
     }
};

// Maruthi Factory
class MaruthiCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
         return new MaruthiEngine;
     }
     CarBody* createCarBodyProduct()
     {
         return new MaruthiBody;
     }

};

// Renault Factory
class RenaultCarFactory : public CarFactory
{
     public:
    CarEngine* createCarEngineProduct()
    {
        return new RenaultEngine;
    }

    CarBody* createCarBodyProduct()
    {
        return new RenaultBody;
    }

};


int main()
{

   // Fiat Factory
   CarFactory* pFiatCarFactory = new FaitCarFactory;
   CarEngine* pFiatEngine = pFiatCarFactory->createCarEngineProduct();
   CarBody*  pFiatBody = pFiatCarFactory->createCarBodyProduct();
   pFiatEngine->engineType();
   pFiatBody->bodyType();

   // Renault Car Factory
    return 0;
}

*/

-1

ファクトリー・メソッド・パターンは、作成されているオブジェクトの正確なクラスを表示せずにオブジェクトの作成を処理する、作成デザイン・パターンです。この設計パターンでは、基本的に、クラスがインスタンス化をサブクラスに委譲できるようにします。

Abstract Factoryパターンは、具象クラスを公開することなく、個々のファクトリーのグループをカプセル化します。このモデルでは、抽象ファクトリクラスの汎用インターフェイスを使用して、オブジェクトの実装の詳細を使用方法や構成から分離する、必要な具象オブジェクトを作成します。このデザインパターンは、同様の種類のGUIコンポーネントを作成する必要があるGUIアプリケーションで広く使用されています。

Googleで検索しているときに、両方のデザインパターンを見事に説明したブログをフォローしました。これらを見てください

http://simpletechtalks.com/factory-design-pattern/

http://simpletechtalks.com/abstract-factory-design-pattern/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.