デザインパターンについて笑う-Xiaobaiはクラスをスキップすることから名付けられました

前書き

ファクトリパターン(ファクトリパターン)は、最も一般的に使用されるデザインパターンの1つです。このタイプのデザインパターンは作成パターンであり、オブジェクトを作成するための最良の方法を提供します。

ファクトリモデルでは、オブジェクトの作成時に作成ロジックをクライアントに公開せず、代わりに、共通のインターフェイスを使用して新しく作成されたオブジェクトをポイントします。

分類

ファクトリモデルは3つのタイプに分けることができます。単純なファクトリは一般にデザインパターンとは見なされませんが、特殊な種類のファクトリメソッドと見なすことができます。

  • シンプルなファクトリ
  • ファクトリメソッド
  • 抽象ファクトリ

シーン分析

普通の退屈なテキストは常に人々を眠りたくさせます次に、いくつかのシナリオを使用して分析します

シンプルなファクトリ

Factory [ファクトリクラス]クラスを介して直接複数のエンティティクラスを作成する構築メソッド。

時間:2021年2月19日場所:教室キャラクター:学生シャオバイ、教師、ビッグブラザーブラックスキン


Xiaobaiは、怠惰で学ぶのが好きではない2年生のコンピューター学生です。今朝の最初のクラスは、私が寝るのが遅かったので先生に捕まりました。このクラスはたまたまシャオバイで最も厄介なコンピュータークラス「C#デザインパターン」でした。いいえ、先生は授業の途中で質問を始め、シャオバイは「見​​事に」先生の名前になりました。

先生は微笑んで「小梅、画面の質問に答えてください」と言った。

トピック:c#、java、python、php、またはその他のオブジェクト指向プログラミング言語を使用して、2つの有効な数値と1つの有効な記号を入力し、対応する結果を出力する機能を実現してください。

Xiaobaiは、それがどのような問題であるかを調べました。それはとても単純でした。私がそれを捕まえなかったのを見て、私の手で叩く音とともに一連のコードが画面に現れました。

**電卓操作クラス**

    public class Calculator
    {
        public double GetResult(double A, double B, string operate)
        {
            double result = 0d;
            switch (operate)
            {
                case "+": 
                    result = A + B;
                    break;
                case "-":
                    result = A - B;
                    break;
                case "*":
                    result = A * B;
                    break;
                case "/":
                    result = A / B;
                    break;
                default: break;
            }
            return result;
        }
    }

クライアントコード

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入数字A");
            string a = Console.ReadLine();
            Console.WriteLine("请输入数字B");
            string b = Console.ReadLine();
            Console.WriteLine("请选择操作符号(+、-、*、/)");
            string operate = Console.ReadLine();

            Calculator box = new Calculator();
            double result = box.GetResult(Convert.ToDouble(a), Convert.ToDouble(b), operate);
            Console.WriteLine(result);
            
            Console.ReadKey();
        }
    }

Xiao Bai:「先生、書き終えました」

先生:「はい、よく書かれています。3つのオブジェクト指向機能のカプセル化が使用され、計算方法が計算クラスにカプセル化されます。複数のクライアントがこのクラスを再利用できます。しかし、多くの問題もあります。どのクラスメートが答えますか。 「」

Hei Pi:「クラスメートのXiaobaiによって書かれたコードには2つの問題があります。

1. A = 10、B = 0と入力すると、プログラムはエラーを報告し、入力の有効性は検証されていません。

2.規定に従って操作記号を入力しないと、エラーも発生します。

先生:「Heipiは非常によく答えましたが、これはコードビジネスロジックエラーの説明にすぎません。誰でもより深い内容を見ることができます。」

Hei Pi:「先生、ヒントを教えていただけませんか。」

先生:「これは少し隠されているかもしれません、先生はヒントを与えます。新しい計算を追加したらどうなりますか?」

Xiaobaiはすぐに、「新しいブランチを追加して切り替えるだけです」と答えました。

先生:「もちろんこれには間違いはありませんが、問題は新しい算術記号を追加しただけですが、足し算、引き算、掛け算、割り算のすべての操作をコンパイルに参加させる必要があります。誤って変更した場合変更プロセス中の他のコードたとえば、+記号を-に変更してもそれほど悪くはありません。これは、開閉の原則に違反します[拡張のために開く、変更のために閉じる]」

シャオバイは頭をかいて、「開閉の原理、これは何?」と尋ねました。

先生:「これは、クラスに注意深く耳を傾けなかった場合に見逃したことです。戻って、良い授業を受けてください。Heipiのクラスメート、先生のポイントを取得したかどうかわかりませんか?」

Heipi:「私はそれを変更する方法を知っています。Xiaobaiは3つのオブジェクト指向機能の1つをカプセル化することを実現しました。実際、他の2つの機能を一緒に使用して、教師が望む機能を完成させることができます。」

Xiao Bai:「ポリモーフィズムと継承?」

Hei Pi:「はい、プログラムを変更して読み終え​​たら、気分が良くなるはずです」

    public class Operate
    {
        public double NumberA { get; set; }
        public double NumberB { get; set; }

        public virtual double GetResult()
        {
            return 0;
        }
    }
    
    public class OperateAdd : Operate
    {
        public override double GetResult()
        {
            return this.NumberA +this.NumberB;
        }
    }
    
    public class OperateSub : Operate
    {
        public override double GetResult()
        {
            return this.NumberA - this.NumberB;
        }
    }

シンプルなファクトリ

    public class OperateFactory
    {
        public static Operate GetOperateFactory(string operate)
        {
            Operate fac = null;
            switch (operate)
            {
                case "+":
                    fac = new OperateAdd();
                    break;
                case "-":
                    fac = new OperateSub();
                    break;
                case "*":
                    fac = new OperateMul();
                    break;
                case "/":
                    fac = new OperateDiv();
                    break;
                default:
                    break;
            }
            return fac;
        }
    }

黒い肌:「最初は、2つのNumberプロパティと仮想メソッドGetResult()を持つ操作クラスです。加算、減算、乗算、除算の4つのメソッドは、操作クラスのサブクラスとして継承されます。継承後、GetResult()メソッドが書き直され、基本クラスが呼び出されます。AとBのパブリック属性は、異なる数学演算を実行します。」

黒い肌:「次に、単純なファクトリを定義し、演算子パラメータを静的メソッドに渡して実際のビジネス処理クラスを取得します。クライアントは処理クラスを取得した後にパラメータを割り当てます。最後にその方法を知っておく必要があります。ステップ。」

Xiaobai:「わかりました。そうすれば、クライアントはこのように呼び出すことができます」。

  static void Main(string[] args)
        {
            Console.WriteLine("请选择操作符号(+、-、*、/)");
            string operateStr = Console.ReadLine();
            Operate operate = OperateFactory.GetOperateFactory(operateStr);
            operate.NumberA = 10;
            operate.NumberB = 4;
            double result = operate.GetResult();
            Console.WriteLine(result);
            Console.ReadKey();
        }

先生:「どちらの生徒も簡単な工場の使い方をマスターしているようです。次に、誰もがこのデザインパターンをより早くマスターできるように、いくつか質問をします。」

先生:「除算の論理を変更したい場合、配当の論理を0に増やすにはどうすればよいですか。

Xiaobai:「OperateDivクラスを直接変更してください。これは他の人には影響しません」

先生:「ルートを開く操作を追加したい場合はどうすればよいですか」

Xiaobai:「新しいクラスを追加すると、Operateはルートオープニングロジックを説明するルートクラスを開きます。ファクトリメソッドに新しい演算子を追加するだけです。新しいオペレーションは別のクラスであり、他のメソッドには影響しません。ボディの影響」。

Xiaobai:「クライアントは変更を加える必要がありますか?」

先生:「クライアントが変更を加えたい場合、クライアントは自分の業務を処理するだけで済みます!」

はい、クライアントはファクトリが何を作成するかを気にしません。ファクトリはブラックボックスです。クライアントはパラメータを渡すだけでよく、ファクトリはコンテンツが生成された後にクライアントにコンテンツを送信する責任があります[クラスをインスタンス化するプロセス]。

長所短所

単純なファクトリパターンのファクトリクラスは、通常、静的メソッドを使用して、受信したさまざまなパラメータを通じてさまざまなオブジェクトインスタンスを返します。コードを変更しないと、コードを拡張することはできません。
利点:クライアントは、製品オブジェクトを直接作成する責任を免除できますが、製品を「消費」するだけです。単純なファクトリパターンは、このアプローチによって責任の分割を実現します。
デメリット:ファクトリクラスはすべてのインスタンスの作成ロジックを集中させるため、高凝集責任分散の原則に違反し、すべての作成ロジックが1つのファクトリクラスに集中します。作成できますクラスは事前に検討する必要があります。新しいクラスを追加する必要がある場合は、ファクトリクラスを変更する必要があります。

ファクトリメソッド

時間:2021年2月19日の午後場所:教室キャラクター:学生シャオバイ、教師、ビッグブラザーブラックスキン

先生:「午前中はデザインパターンを続けます。午前中はシンプルファクトリについて話し、午後は次のコンテンツファクトリメソッドについて話します。ファクトリメソッドとシンプルファクトリは実際には同じように、唯一の違いは、抽象クラス(製品とも呼ばれます。つまり、午前中に定義された加算、減算、乗算、除算の4つのサブカテゴリ)の各実装に、対応するファクトリを作成することです。学生はコンテンツについて学習します。先生の言葉を聞いて、それを達成するためのシーンコードを見つけます。最速の完了には教室の報酬があります。」

...数分が経過しました...

Xiao Bai:「先生、私は終わりました。」

先生:「さて、Xiaobaiにシーンと実現方法を説明してもらいましょう。」

果物をシーンにした柄をデザインしました。

1.抽象クラスFruit.csを定義します。このクラスは、2つの抽象メソッドprintfColor()printfName()を定義します

2. 2つの異なるフルーツがそれぞれこの抽象クラスを継承し、抽象メソッドを複製することを実現します。

3.ファクトリインターフェイスを定義し、インターフェイスメソッドcreateFruit()を定義します

4.2つの異なる工場でそれぞれフルーツインスタンスの作成を実現します。

フルーツ抽象クラス

    public abstract class Fruit
    {
        public abstract void PrintfColor();
        public abstract void PrintfName();
    }
    
  public class Apple : Fruit
    {
        public override void PrintfColor()
        {
            Console.WriteLine("红色");
        }

        public override void PrintfName()
        {
            Console.WriteLine("苹果");
        }
    }

ファクトリインターフェイス

   public interface IFruitFactory
    {
        Fruit CreateFruit();
    }

    public class AppleFactory : IFruitFactory
    {
        public Fruit CreateFruit()
        {
            return new Apple();
        }
    }

クライアントの実装

           //苹果工厂
            IFruitFactory appleFac = new AppleFactory();
            Fruit apple = appleFac.CreateFruit();
            apple.PrintfColor();
            apple.PrintfName
            
            //橘子工厂
            IFruitFactory orangeFac = new OrangeFactory();
            Fruit orage = orangeFac.CreateFruit();
            orage.PrintfColor();
            orage.PrintfName();

先生:「同級生のシャオバイは朝の内容をよく理解しているようで、授業を受けてから新しい知識を身につけることができるのは事実です。授業をスキップしても意味がありません。」

先生:「このケースは単純すぎるだけです。他の生徒はなぜこれが当てはまるのかよく理解していないかもしれません。理解のために実際的なケースを紹介します。実際の作業プロセスでは、常に次のようなログコンポーネントを使用します。 Nlogとして、Log4net、構成可能なマルチソース出力をサポートするサードパーティコンポーネント。構成ファイル(json / xml)に「コンソールへのパラメーター出力」を追加すると、プログラムはコンテンツをコンソールに出力します。 、ファイルへのパラメータ入力が設定されると、プログラムは指定されたファイルにコンテンツを出力します。このシナリオの実現は、実際には典型的な工場の方法です。以下のプロセスを分析しましょう。」

1.構成ファイル(json / xml)を読み取ります

2.すべての構成メソッドを取得し、ループスルーします

3.ファイルへの構成入力である場合は、構成タイプを判別します。newはファイルログファクトリであり、後のメソッド呼び出しを容易にするために構成情報をパラメータとして渡します。コンソールへの構成入力の場合。新しいログファクトリも同じ操作を行います

4.各ファクトリは独自の業務のみを管理しますすべてログ出力インターフェイスが必要です。

5.上位層がprintメソッドを呼び出すと、すべてのファクトリをループしインターフェイスのログ出力メソッドを呼び出します。

長所短所

factoryメソッドは、各製品のファクトリクラスを提供することです。さまざまなファクトリインスタンスを介してさまざまな製品インスタンスを作成します。同じ階層構造で、あらゆる製品の追加をサポートします。
長所:特定の工場の役割を変更せずにシステムが新製品を導入できるようにします。
短所:各製品が追加されるため、製品工場カテゴリを追加する必要があります。追加の開発の量を増やします。

抽象ファクトリ

抽象ファクトリパターンは、オブジェクトのセットを作成するためのソリューションを提供します。ファクトリメソッドパターンと比較すると、抽象ファクトリパターンの具体的なファクトリは、製品を作成するだけでなく、製品のファミリを作成する責任があります。

時間:2021年2月20日の朝場所:教室のキャラクター:学生Xiaobai、教師、黒い肌

新しい日が再び始まりました。Xiaobaiの目には、「デザインパターン」コースはそれほど複雑ではないようです。Xiaobaiは今日早く教室に到着し、先生の新しい拍車を迎える準備ができました。

先生:「おはようございます、クラスメート、今日は昨日のコースを続けます。昨日はファクトリメソッドについて話しました。今日はこれに基づいて少し改善し、新しい変更があるかどうかを確認します。Xiaobaiは学習に対する高い熱意を持っています。今、私は最初の列に座っていることがわかりました。悪くはありませんが、励ます価値があります。」

シャオバイ:「ヒヒ」

先生:「さて、今日のコースを始めましょう。今日お話しするモデルは抽象ファクトリモデルです。ファクトリモデルと比較することで、学生は2つの違いを明確に見つけることができます。昨日のXiaobaiの例を引き続き使用します。開いてください。」

現時点では、アップルファクトリーとオレンジファクトリーに対応するアップルとオレンジの2つの製品があります。これは、ファクトリメソッドの実施形態です。しかし、3つの異なる工場がある場合、それらはすべてリンゴとオレンジを生産します。

Xiao Bai:「それでは、さらに工場を建設します。各製品は異なる工場に対応します。そのような構造にする必要があり、各工場は製品の種類に対応します。」

A

  • A_Apple Factory.cs
  • A_Orange Factory.cs

B

  • B_Apple Factory.cs
  • B_Orange Factory.cs

C

  • C_Apple Factory.cs
  • C_Orange Factory.cs

先生:「もちろんこの方法は可能です。10の工場がある場合、10 * 2 = 20のクラスを作成する必要があります。そうすると、プログラムの複雑さが直線的に増加し、メンテナンスに役立ちません。」

Xiao Bai:「では、先生が言ったような抽象ファクトリを使用しますか?それを使用する場合は、どうすればよいですか?」

先生:「はい、そのようなシナリオでは、抽象ファクトリが最も一致するデザインパターンです。実際、方法は非常に単純で、昨日のコードにいくつかの変更を加えるだけです。」

フルーツ抽象クラス

後でさまざまな工場の印刷を容易にするために、新しいName属性が追加されました。

    public abstract class Fruit
    {
        public string Name { get; set; }
        public abstract void PrintfColor();
        public abstract void PrintfName();
    }
    
    public class Apple : Fruit
    {
        public Apple(string name)
        {
            this.Name = name;
        }

        public override void PrintfColor()
        {
            Console.WriteLine(this.Name + "红色");
        }

        public override void PrintfName()
        {
            Console.WriteLine(this.Name + "苹果");
        }
    }

ファクトリインターフェイス

先生:「この場所での変更はより明白です。各ファクトリは以前に1つの製品しか生産しなかったため、元のインターフェイスのメソッドは唯一の製品を出力します。現在は2つの製品を出力します。つまり、ファクトリインターフェイスを継承するクラスは実装する必要がありますリンゴの生産とオレンジの方法。これの利点は、各工場が独自の製品の実現を管理する責任があり、製品ごとに工場を作成する必要がないことです。」

説明:

工場ではリンゴとオレンジを生産しています。複数の工場がある場合、各工場はリンゴとオレンジの生産を実現します。工場Aのリンゴを生産する代わりに、工場実装クラスが必要であり、工場Bのリンゴを生産するには別のクラスが必要です。次のように

古いモデル

A

  • A_アップルファクトリー。
  • A_オレンジファクトリー

B

  • B_アップルファクトリー
  • B_オレンジファクトリー

C

  • C_Appleファクトリー

ニューモデル

工房

  • アップル/オレンジ

Bファクトリー

  • アップル/オレンジ

Cファクトリー

  • アップル/オレンジ

先生:「このようにして、複雑さは6から3に変わりました。」

Xiao Bai:「わかりました、そして新しいことを学びました。」

    public interface IFruitFactory
    {
        Fruit CreateApple(string name);
        Fruit CreateOrange(string name);
    }

    public class AFactory : IFruitFactory
    {
        public Fruit CreateApple(string name)
        {
            return new Apple(name);
        }

        public Fruit CreateOrange(string name)
        {
            return new Orange(name);
        }
    }

クライアントの実装

            IFruitFactory fac = new AFactory();
            Fruit a_Apple = fac.CreateApple("a工厂");
            Fruit a_Orange = fac.CreateOrange("a工厂");
            a_Apple.PrintfName();
            a_Orange.PrintfName();

            IFruitFactory b_fac = new BFactory();
            Fruit b_Apple = b_fac.CreateApple("b工厂");
            Fruit b_Orange = b_fac.CreateOrange("b工厂");
            b_Apple.PrintfName();
            b_Orange.PrintfName();

Xiao Bai:「しかし、このモードをどのようなシーンで使用すればよいのか、一度にすべてを考えることはできないようです」

先生:「抽象ファクトリの使用は比較的少ないですが、それらがないわけではありません。例を挙げましょう。バックエンドの最初に、さまざまなコンポーネント[ボタン、引き出し、ナビゲーションバー]などがあり、これらのコンポーネントがあります対応するスキンがあり、スキンの開発は抽象的なファクトリの実現です。ファクトリインターフェイスは各コンポーネントの定義であり、各スキ​​ンはファクトリの実現です。スキンを切り替えたい場合は、さまざまなファクトリをインスタンス化するだけで済みます。 「」

Xiao Bai:「ああ、ゲームのスキン切り替えと同じですか?」

先生:「この方法でも理解できます。デザインパターンは、さまざまなシナリオに適用できる一般的なソリューションにすぎません。自分に最も適し、最もよく理解できるシナリオを選択できます。」

授業終了後、再びベルが鳴った

先生:「さて、このクラスはここで終わります。次のクラスでは、他のデザインパターンについて話します。みんなが時間通りにそれらを聞いてくれることを願っています。」

長所短所

抽象ファクトリは、製品ファミリの概念を扱うことです。製品ファミリの概念に応じて、新しい製品ラインを追加することは簡単ですが、新しい製品を追加することは不可能です。たとえば、各自動車会社が自動車、トラック、バスを同時に生産する可能性があるため、すべての工場で自動車、トラック、バスを作成する方法が必要です。
利点:クライアントにインターフェイスを提供し、クライアントが作成しないようにします。特定のタイプの製品を指定する必要があるこの場合、複数の製品ファミリで製品オブジェクトを作成します。
短所:新しい製品レベル構造の追加は非常に複雑です。抽象ファクトリとすべての具体的なファクトリクラスを変更する必要があります。 「開閉原理」は傾いている

おすすめ

転載: blog.csdn.net/HapplyFox/article/details/113878228