FactoryとAbstract Factoryのパターンの基本的な違いは何ですか?
Factoryパターンを使用すると、特定のインターフェースの実装(Apple
、Banana
、Cherry
など)のインスタンス(IFruit
など)を生成します。
Abstract Factoryパターンでは、誰でも自分のファクトリを提供する方法を提供します。これにより、あなたの倉庫が果物やジュースについて何も知らなくても、あなたの倉庫をIFruitFactory
またはIJuiceFactory
にすることができます。
抽象ファクトリのメソッドはファクトリメソッドとして実装されています。抽象ファクトリパターンとファクトリメソッドパターンはどちらも、抽象型とファクトリを介してクライアントシステムを実際の実装クラスから切り離します。 Factoryメソッドは継承によってオブジェクトを作成し、Abstract Factoryは合成によってオブジェクトを作成します。
Abstract Factoryパターンは、AbstractFactory、ConcreteFactory、AbstractProduct、ConcreteProduct、およびクライアントで構成されています。
抽象ファクトリパターンは、ファクトリメソッドパターン、プロトタイプパターン、またはシングルトンパターンを使用して実装できます。 ConcreteFactoryオブジェクトのインスタンスは1つだけ必要なので、ConcreteFactoryオブジェクトはシングルトンとして実装できます。
ファクトリメソッドパターンは、抽象ファクトリパターンの簡易版です。ファクトリーメソッドパターンは1つのファミリーに属する製品を作成する責任がありますが、抽象ファクトリーパターンは複数のファミリーの製品を扱います。
Factory Methodは、インタフェースと抽象クラスを使用して、ジェネレータクラスとその結果生成される製品からクライアントを分離します。 Abstract Factoryには、クライアントとジェネレータおよび製品を分離するインタフェースとともに、いくつかのファクトリメソッドのコンテナとなるジェネレータがあります。
使用する特定の製品からクライアントを切り離す必要がある場合は、Factory Methodパターンを使用してください。ファクトリメソッドを使用して、製品のインスタンスを作成および構成する責任をクライアントから解放します。
クライアントを製品クラスから切り離す必要がある場合は、Abstract Factoryパターンを使用してください。プログラムの設定や修正に特に便利です。 Abstract Factoryパターンは、どのクラスを他のクラスと一緒に使用する必要があるかについても制約を強制できます。新しいコンクリート工場を作るのは大変な作業かもしれません。
パスタメーカーで異なるタイプのパスタを準備するためのディスクのこの仕様は抽象ファクトリであり、それぞれの特定のディスクはファクトリです。すべてのファクトリー(パスタメーカーのディスク)は抽象ファクトリーからその特性を継承しています。個々のディスクには、パスタの作成方法に関する情報が含まれていますが、パスタメーカーには含まれていません。
Stamping Equipmentは、抽象的な製品オブジェクトを作成する操作のためのインタフェースであるため、Abstract Factoryに対応しています。彼らは具体的な製品を作成するように金型は、コンクリート工場に対応しています。各部品カテゴリ(フード、ドアなど)は抽象製品に対応しています。特定の部品(99カムリ用の運転席側ドア)はコンクリート製品に対応します。
おもちゃ会社は、製品オブジェクトを作成するためにファクトリーを使用する可能性があるため、作成者に対応します。特定の種類のおもちゃ(馬や車)を製造するおもちゃ会社の部門は、ConcreteCreatorに対応します。
ファクトリーパターン:ファクトリーはIProductを実装しています
抽象的なファクトリーパターン:ファクトリーファクトリーはIFactoriesを生成し、それは次にIProductsを生成します:)
[コメントに従って更新する]
私が先に書いたことは、少なくとも Wikipedia によれば正しくありません。抽象ファクトリは単にファクトリインタフェースです。それを使用すると、実行時にファクトリを切り替えて、さまざまなコンテキストでさまざまなファクトリを許可できます。例は、異なるOS、SQLプロバイダ、ミドルウェアドライバなどのための異なるファクトリかもしれません。
具象クラスを指定せずに、関連または従属オブジェクトのファミリーを作成するためのインターフェースを提供します。
Abstract Factoryパターンは、Factory Methodパターンと非常によく似ています。両者の1つの違いは、抽象ファクトリパターンでは、クラスがコンポジションを介してオブジェクトのインスタンス化の責任を別のオブジェクトに委任するのに対し、ファクトリメソッドパターンは継承を使用し、サブクラスに依存して目的のオブジェクトのインスタンス化を処理することです。
実際には、委譲されたオブジェクトはインスタンス化を実行するためにファクトリメソッドを頻繁に使用します。
工場のパターンは創造的なパターンの例です
作成パターンは、オブジェクトのインスタンス化プロセスを抽象化します。それらは、オブジェクトがどのように作成され、どのように作成され、構成されているかからシステム全体を独立させるのを助けます。
クラス作成パターンは、インスタンス化するオブジェクトを決定するための継承の使用に焦点を当てますファクトリメソッド
オブジェクト生成パターンは、インスタンス化から別のオブジェクトへの委任に焦点を当てています
参照: ファクトリーvs抽象ファクトリー
ファクトリメソッド:特定の基本クラスから派生したオブジェクトを作成するファクトリがあります。
抽象ファクトリ:他のファクトリを作成するファクトリがあり、これらのファクトリは次に派生オブジェクトを作成します。基本クラスこれは、(Factoryメソッドのように)単一のオブジェクトを作成したくない場合が多いためです。むしろ、関連オブジェクトのコレクションを作成する必要があります。
抽象ファクトリは関連オブジェクトを作成するためのインタフェースですが、ファクトリメソッドはメソッドです。抽象ファクトリはファクトリメソッドで実装されています。
基本的な違い:
ファクトリ:インスタンス化ロジックをクライアントに公開せずにオブジェクトを作成します。
ファクトリメソッド:オブジェクトを作成するためのインタフェースを定義しますが、どのクラスをインスタンス化するかはサブクラスに決定させます。 Factoryメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。
抽象ファクトリ:具象クラスを指定せずに、関連または従属オブジェクトのファミリを作成するためのインタフェースを提供します。
AbstractFactoryパターンはコンポジションを使用してオブジェクトを作成する責任を別のクラスに委任します。ファクトリメソッドパターンは継承を使用し、派生クラスまたはサブクラスを使用してオブジェクトを作成します
oodesign articlesから:
ファクトリ クラス図:
例:StaticFactory
public class ShapeFactory {
//use getShape method to get object of type shape
public static Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
FactoryMethodを実装した非静的ファクトリの例はこの投稿で利用できます。
デザインパターン:Factory vs Factoryメソッドvs Abstract Factory
使用する場合:クライアントはクラスを必要とするだけで、どの具体的な実装を取得しても構いません。
ファクトリメソッド class digaram:
使用する場合:クライアントは実行時にどの具体的なクラスを作成する必要があるのかわかりませんが、仕事をするクラスを取得したいだけです。
使用する時期:システムが複数の製品ファミリを作成する必要がある場合、または実装の詳細を公開せずに製品のライブラリを提供する場合。
上記の記事のソースコードの例は、概念を明確に理解するのに非常に役立ちます。
コード例が含まれる関連するSE質問
違い:
その他の役に立つ記事
factory_method ソース作成から
abstract_factory from sourcemaking
abstract-factory-design-pattern from journaldev
抽象ファクトリの例/シナリオ
私は雨季に雨が降り、冬は雪が降り、夏は暑くて晴れの場所に住んでいます。私は要素から身を守るために異なる種類の服が必要です。そうするために私は私の家の近くの店に行き、自分自身を守るために衣類/アイテムを求めます。店の番人は私のポケットの環境そして深さに従って私に適切な項目を与える。彼が私にくれるアイテムは同じレベルの品質と価格帯です。彼は私の標準を知っているので、彼がそうするのは簡単です。しかし、通りの向こうから金持ちの男が同じ要件を思いつくと、彼は高価な、ブランドのアイテムを手に入れます。注目すべき点の1つは、彼が私に提供しているすべての項目が、品質、標準、およびコストの点で互いに補完し合うことです。彼らはお互いに行くと言うことができます。この金持ちが得たアイテムの場合も同じです。
だから上記のシナリオを見て、私は今店主の効率性に感謝します。私はこの店主を抽象ショップに置き換えることができます。私達が抽象アイテムと私と私たちと遠近法クライアントとしての金持ちで手に入れるアイテム。私たちが必要としているのは、私たちのニーズに合った商品/アイテムだけです。
今、私は自分自身をその多数の顧客に一連のサービスを提供するオンラインストアを検討しているのを容易に見ることができます。各クライアントは、3つのグループのいずれかに属しています。プレミアムグループのユーザーがサイトを開くと、優れたUI、高度にカスタマイズされた広告枠、メニューのオプションなどが表示されます。これらの同じ機能セットはゴールドユーザーにも提供されますが、メニューの機能は少なくなります。そしてやや少ない人間工学的なUI。最後は私の種類のユーザー、「フリーグループ」ユーザーです。私は気分が悪くならないように十分に奉仕されています。 UIは最低限必要なもので、広告はあまりにもトラックから外れているので、何が表示されるのかわからないので、最後にメニューからログアウトするだけです。
私がこのウェブサイトのようなものを構築する機会があれば、私は間違いなくAbstract Factory Patternを検討するでしょう。
抽象的な製品:広告ペイン、メニュー、UIペインタ。
Abstract Factory:Webストアのユーザーエクスペリエンス
Concreate Factory:プレミアムユーザーエクスペリエンス、ゴールドユーザーエクスペリエンス、一般ユーザーエクスペリエンス。
多くの人が多分驚くかもしれませんが、この質問は間違っています。面接中にこの質問を聞いた場合は、面接官が混乱がどこにあるのかを理解するのを助ける必要があります。
「ファクトリー」と呼ばれるような具体的なパターンがないことから始めましょう。 「抽象ファクトリー」と呼ばれるパターンがあり、「ファクトリーメソッド」と呼ばれるパターンがあります。
それでは、「工場」とはどういう意味ですか?次のいずれか(参照の範囲に応じて、すべて正しいと見なすことができます)。
そして、残念ながら、多くの人が "Factory"を使って別の種類のファクトリーを表し、ファクトリーまたはファクトリー(またはそれらのインターフェース)を作成します。彼らの理論に基づいて:
ProductはIProductを実装し、これはFactoryによって作成され、IFactoryを実装します。これはAbstractFactoryによって作成されます。
これがどれほどばかげているかを理解するために、私たちの方程式を続けましょう。
AbstractFactoryはIAbstractFactoryを実装しています。これは... AbstractAbstractFactoryで作成されましたか。
私はあなたがその点を見てくれることを願っています。混乱しないでください、そして理由のために存在しないものを発明しないでください。
-
P.S。:Factory for ProductsはAbstractFactoryであり、Factory for Abstract FactoryiesもAbstractFactoryのほんの一例です。
//Abstract factory - Provides interface to create factory of related products
interface PizzaIngredientsFactory{
public Dough createDough(); //Will return you family of Dough
public Clam createClam(); //Will return you family of Clam
public Sauce createSauce(); //Will return you family of Sauce
}
class NYPizzaIngredientsFactory implements PizzaIngredientsFactory{
@Override
public Dough createDough(){
//create the concrete dough instance that NY uses
return doughInstance;
}
//override other methods
}
教科書の定義はすでに他の答えによって提供されています。私はそれの例も提供しようと思いました。
それで、ここでPizzaIngredientsFactory
は抽象ファクトリです。関連する製品のファミリーを作成するためのメソッドを提供するからです。
抽象ファクトリの各メソッドは、それ自体がファクトリメソッドです。 createDough()
のようにそれ自体はファクトリメソッドであり、その具体的な実装はNYPizzaIngredientsFactory
のようなサブクラスによって提供されます。そのため、これを使用して、それぞれ異なる場所で、その場所に属するコンクリート原料のインスタンスを作成できます。
具体的な実装のインスタンスを提供します
例では:
- createDough()
- 生地の具体的な実装方法を説明します。だからこれはファクトリーメソッドです
関連オブジェクトのファミリーを作成するためのインターフェースを提供します
例では:
- PizzaIngredientsFactory
は、Dough
、Clams
、Sauce
のようなオブジェクトの関連セットを作成することを可能にするため、抽象ファクトリです。各オブジェクトファミリを作成するためにファクトリメソッドを提供します。
私は次のようにジョンの答えに貢献するいくつかのポイントがあります:
"Factory Method"(単に "Factory"はあいまいなので)を使用して、特定のインターフェースの実装(Lemon
、Orange
など)を作成します。たとえばIFruit
です。このファクトリーはCitricFruitFactory
と呼ばれることがあります。
しかし今、あなたはCitricFruitFactoryが作成することができない他の種類の果物を作成したいです。 CitricFruitFactory
というコードを作成しても、Strawberry
のコードは意味がありません(ストロベリーはクエン酸の果物ではありません)。
そのため、RedFruitFactory
、Strawberry
などを生成するRaspberry
という新しいFactoryを作成できます。
John Feminellaが言ったように: "Abstract Factoryパターンでは、特定のFactoryインタフェースの実装を生成します - 例えばIFruitFactory
それぞれが違う種類の果物を作る方法を知っています。 "
IFruitFactory
の実装はCitricFruitFactory
とRedFruitFactory
です。
John Feminellaの答えを拡張する:
Apple
、Banana
、Cherry
はFruitFactory
を実装しており、それはCreate
と呼ばれるメソッドを持っています。 Factory
メソッドで完了です。
さて、あなたはあなたの果物のうち特別なサラダをCreate
したいと思います、そしてあなたのAbstract Factoryがやってきます。 Abstract Factoryは、Apple、Banana、Cherryからあなたの特別なサラダを作り出す方法を知っています。
public class Apple implements Fruit, FruitFactory {
public Fruit Create() {
// Apple creation logic goes here
}
}
public class Banana implements Fruit, FruitFactory {
public Fruit Create() {
// Banana creation logic goes here
}
}
public class Cherry implements Fruit, FruitFactory {
public Fruit Create() {
// Cherry creation logic goes here
}
}
public class SpecialSalad implements Salad, SaladFactory {
public static Salad Create(FruitFactory[] fruits) {
// loop through the factory and create the fruits.
// then you're ready to cut and slice your fruits
// to create your special salad.
}
}
私の情報源はStackOverflow
、tutorialspoint.com
、programmers.stackexchange.com
およびCodeProject.com
です。
Factory Method
(Factory
とも呼ばれます)はInterface
実装のデカップリングクライアント用です。サンプルとして、2つのShape
とCircle
を実装したSquare
インターフェースがあります。 Type
のような決定パラメータを持つファクトリメソッドと、Shape
インタフェースの新しい関連実装を持つファクトリクラスを定義しました。
Abstract Factory
には、いくつかのファクトリ実装またはいくつかのファクトリ実装によるファクトリインタフェースが含まれています。次の上記のサンプルでは、2つのColor
とRed
の実装を持つYellow
インターフェースがあります。 2つのShapeColorFactory
とRedCircleFactory
を使ってYellowSquareFactory
インターフェースを定義しました。この概念を説明する次のコード:
interface ShapeColorFactory
{
public Shape getShape();
public Color getColor();
}
class RedCircleFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Circle();
}
@Override
public Color getColor() {
return new Red();
}
}
class YellowSquareFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Square();
}
@Override
public Color getColor() {
return new Yellow();
}
}
これがFactoryMethod
とAbstractFactory
の違いです。 Factory Method
は単純にインターフェースの具象クラスを返しますが、Abstract Factory
はfactory of factory
を返します。言い換えれば、Abstract Factory
は一連のインターフェースの異なる組み合わせを返します。
私の説明がお役に立つことを願っています。
これらの工場の主な違いは、工場で何をしたいのか、そしていつ使いたいのかということです。
ときには、IOC(コンストラクタインジェクションなどの制御の反転)を行っているときに、ソリッドオブジェクトを作成できることがわかります。果物の例で述べたように、果物のオブジェクトを作成する準備が整ったら、単純なファクトリパターンを使うことができます。
しかし、多くの場合、ソリッドオブジェクトを作成したくはありません。それらはプログラムフローの後半で表示されます。しかし、構成は、オブジェクトを作成する代わりに、起動時にどの種類のファクトリーを使用するかを指示します。共通のファクトリークラスから派生したファクトリーをIOCのコンストラクターに渡すことができます。
だから、私はそれがオブジェクトの寿命と創造についても考えています。
定義により、2つの違いを引き出すことができます。
Factory:オブジェクトを作成するためにインタフェースが使用されますが、サブクラスはどのクラスをインスタンス化するかを決定します。オブジェクトの作成は必要なときに行われます。
抽象ファクトリー:抽象ファクトリー・パターンは、他のファクトリーを作成するスーパーファクトリーとして機能します。 Abstract Factoryパターンでは、インターフェースは、具象クラスを指定せずに、一連の関連オブジェクト、または従属オブジェクトを作成します。
したがって、上記の定義では、特定の違いを強調することができます。つまり、Factoryパターンがオブジェクトの作成を担当し、Abstract Factoryが一連の関連オブジェクトの作成を担当します。明らかに両方ともインターフェースを通してです。
工場パターン:
public interface IFactory{
void VehicleType(string n);
}
public class Scooter : IFactory{
public void VehicleType(string n){
Console.WriteLine("Vehicle type: " + n);
}
}
public class Bike : IFactory{
public void VehicleType(string n) {
Console.WriteLine("Vehicle type: " + n);
}
}
public interface IVehicleFactory{
IFactory GetVehicleType(string Vehicle);
}
public class ConcreteVehicleFactory : IVehicleFactory{
public IFactory GetVehicleType(string Vehicle){
switch (Vehicle){
case "Scooter":
return new Scooter();
case "Bike":
return new Bike();
default:
return new Scooter();
}
}
class Program{
static void Main(string[] args){
IVehicleFactory factory = new ConcreteVehicleFactory();
IFactory scooter = factory.GetVehicleType("Scooter");
scooter.VehicleType("Scooter");
IFactory bike = factory.GetVehicleType("Bike");
bike.VehicleType("Bike");
Console.ReadKey();
}
}
抽象的な工場パターン:
interface IVehicleFactory{
IBike GetBike();
IScooter GetScooter();
}
class HondaFactory : IVehicleFactory{
public IBike GetBike(){
return new FZS();
}
public IScooter GetScooter(){
return new FZscooter();
}
}
class HeroFactory: IVehicleFactory{
public IBike GetBike(){
return new Pulsur();
}
public IScooter GetScooter(){
return new PulsurScooter();
}
}
interface IBike
{
string Name();
}
interface IScooter
{
string Name();
}
class FZS:IBike{
public string Name(){
return "FZS";
}
}
class Pulsur:IBike{
public string Name(){
return "Pulsur";
}
}
class FZscooter:IScooter {
public string Name(){
return "FZscooter";
}
}
class PulsurScooter:IScooter{
public string Name(){
return "PulsurScooter";
}
}
enum MANUFACTURERS
{
HONDA,
HERO
}
class VehicleTypeCheck{
IBike bike;
IScooter scooter;
IVehicleFactory factory;
MANUFACTURERS manu;
public VehicleTypeCheck(MANUFACTURERS m){
manu = m;
}
public void CheckProducts()
{
switch (manu){
case MANUFACTURERS.HONDA:
factory = new HondaFactory();
break;
case MANUFACTURERS.HERO:
factory = new HeroFactory();
break;
}
Console.WriteLine("Bike: " + factory.GetBike().Name() + "\nScooter: " + factory.GetScooter().Name());
}
}
class Program
{
static void Main(string[] args)
{
VehicleTypeCheck chk = new VehicleTypeCheck(MANUFACTURERS.HONDA);
chk.CheckProducts();
chk= new VehicleTypeCheck(MANUFACTURERS.HERO);
chk.CheckProducts();
Console.Read();
}
}
Factory Method
とAbstract Factory
はどちらもクライアントを具象型から切り離します。どちらもオブジェクトを作成しますが、Factory
メソッドは継承を使用しますが、Abstract Factory
はコンポジションを使用します。
Factory Method
は具象オブジェクト(製品)を作成するためにサブクラスで継承されますが、Abstract Factory
は関連製品のファミリーを作成するためのインターフェースを提供し、これらのインターフェースのサブクラスは関連製品の作成方法を定義します。
次に、これらのサブクラスはインスタンス化されると製品クラスに渡され、そこで抽象型として使用されます。 Abstract Factory
の関連製品は、Factory Method
を使って実装されることがよくあります。
Abstract Factoryは、さまざまなタイプのインターフェースを作成するためのテンプレートです。数量、価格、商品固有の情報など、さまざまな種類のcsvファイルを解析する必要があるプロジェクトがあるとします。解析後、対応するデータベースでこの情報を更新する必要があります。 1つの抽象ファクトリがあなたにパーサとモディファイアファクトリを返すと、このパーサファクトリはあなたにチョコレートパーサオブジェクト、フルーツパーサオブジェクトなどを返すことができます。
こちらをチェックしてください。 http://www.allapplabs.com/Java_design_patterns/abstract_factory_pattern.htm Factoryメソッドは特定のクラス(抽象ではない)を次のように使用しているようです。抽象ファクトリがこれに抽象クラスを使用するのに対し、基本クラス。また、抽象クラスの代わりにインタフェースを使用すると、結果は抽象ファクトリパターンの異なる実装になります。
:D
Java8のサンプルコードを見れば、これら2つの違いを理解できると思います。
interface Something{}
interface OneWhoCanProvideSomething {
Something getSomething();
}
interface OneWhoCanProvideCreatorsOfSomething{
OneWhoCanProvideSomething getCreator();
}
public class AbstractFactoryExample {
public static void main(String[] args) {
//I need something
//Let's create one
Something something = new Something() {};
//Or ask someone (FACTORY pattern)
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeA = () -> null;
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeB = () -> null;
//Or ask someone who knows soemone who can create something (ABSTRACT FACTORY pattern)
OneWhoCanProvideCreatorsOfSomething oneWhoCanProvideCreatorsOfSomething = () -> null;
//Same thing, but you don't need to write you own interfaces
Supplier<Something> supplierOfSomething = () -> null;
Supplier<Supplier<Something>> supplierOfSupplier = () -> null;
}
}
今度の問題は、どの作成方法を使用すべきか、そしてその理由です。最初の方法(パターンなし、単なるコンストラクタ):自分で作成することはお勧めできません。すべての作業を実行する必要があります。特定の実装.
2つ目の方法(ファクトリパターンを使用):あなたはあなたが何らかの条件(おそらく作成メソッドに渡されるパラメータ)に基づいて異なるタイプの何かを提供することができる任意のタイプの実装を渡すことができるという利点を提供します。
3番目の方法(Abstract Factoryパターンを使用):これにより、柔軟性が高まります。あなたは何らかの条件(おそらく渡されたパラメータ)に基づいて何かの種類のクリエイターを見つけることができます。
2つの条件を組み合わせることでいつでもFactoryパターンを回避できることに注意してください(これによりコードの複雑さと結合がわずかに増加します)。 Abstract Factoryパターンのライフユースケース