定義:クラス、モジュール、関数などのソフトウェアエンティティは、拡張機能に開放され、修正に閉じられている必要があります。
問題の起源:ソフトウェアのライフサイクル中に、変更、アップグレード、メンテナンスのためにソフトウェアの元のコードを変更する必要がある場合、エラーが古いコードに導入される場合があります。また、関数全体をリファクタリングするように強制され、元のコードを再検討する必要があります。
解決策:ソフトウェアを変更する必要がある場合は、既存のコードを変更するのではなく、ソフトウェアエンティティの動作を拡張することにより、変更を達成してみてください。
開閉の原則は、オブジェクト指向の設計における最も基本的な設計原則であり、安定した柔軟なシステムを確立する方法を導きます。開閉の原則は、デザインパターンの6つの原則の最も曖昧な定義である可能性があります。それは私たちに、修正を開いて閉じることを指示するだけですが、どうすれば私たちを開いて閉鎖することができ、はっきりと教えてはいけません。過去に、誰かが「設計時に開閉の原則を守らなければならない」と言ったら、彼は何も言わなかったと思うが、彼はすべてを言ったようだった。開閉の原則は本当に空いているからです。
デザインパターンに関する多くの記事を注意深く考えて読んだ後、私はついに開閉の原則を少し理解しました。実際、設計パターンの最初の5つの原則に従い、23の設計パターンを使用する目的は、開閉原則に従うことです。言い換えれば、最初の5つの原則を順守している限り、設計されたソフトウェアは、オープニングとクロージングの原則に自然に適合します。このオープニングとクロージングの原則は、最初の5つの原則のコンプライアンスの程度の「平均スコア」に似ています。前の5つの原則が十分に守られている場合、平均スコアは自然に高くなります。つまり、ソフトウェアの設計の開閉原則が十分に守られています。前の5つの原則が順守されていない場合、それは開会と閉会の原則が順守されていないことを意味します。
実際、著者は、開閉の原則は意味を表現すること以外の何物でもないと考えています。抽象化とともにフレームワークを構築し、実装で詳細を拡大することです。抽象化の柔軟性と幅広い適応性のため、抽象化が合理的である限り、ソフトウェアアーキテクチャの安定性を基本的に維持できます。ソフトウェアの変数の詳細については、要約から派生した実装クラスを使用して拡張します。ソフトウェアを変更する必要がある場合、拡張する必要性に応じて実装クラスを再派生するだけです。もちろん、前提は、私たちの抽象化は合理的でなければならず、私たちは需要の変化において前向きで予見されなければならないということです。
開口部と閉鎖の原則の定義では、ソフトウェアエンティティは、ソフトウェアモジュール、複数のクラスで構成されるローカル構造、または独立したクラスを指す場合があります。
どのソフトウェアも重要な問題に直面する必要があります。つまり、そのニーズは時間とともに変化します。ソフトウェアシステムが新しいニーズに直面する必要がある場合、システム設計フレームワークが安定していることを確認するために最善を尽くしてください。ソフトウェアの設計が開閉の原則に準拠している場合、システムを拡張するのが非常に便利であり、拡張時に既存のコードを変更する必要はありません。そのため、ソフトウェアシステムは適応性と柔軟性を持ちながら安定性と連続性が向上します。ソフトウェアスケールがますます大きくなるにつれて、ソフトウェアの寿命が長くなり、ソフトウェアのメンテナンスコストがますます高くなり、開閉原則を満たすソフトウェアシステムの設計がますます重要になっています。
開閉の原則を満たすためには、システムを抽象的に設計する必要があり、抽象化は開閉の原則の鍵です。 JavaやC#などのプログラミング言語では、システムに対して比較的安定した抽象化レイヤーを定義でき、さまざまな実装動作を特定の実装レイヤーに移動して完了することができます。多くのオブジェクト指向のプログラミング言語では、インターフェイスや抽象クラスなどのメカニズムが提供され、システムの抽象化層を定義し、コンクリートクラスを通じて拡張できます。システムの動作を変更する必要がある場合、抽象化レイヤーに変更を加える必要はありません。既存のコードを変更せずにシステムの機能を拡張し、開閉原則の要件を満たすために、新しいビジネス機能を実装するために新しいコンクリートクラスを追加するだけです。
Sunnyソフトウェアによって開発されたCRMシステムは、パイチャートやバーチャートなど、さまざまな種類のチャートを表示できます。複数のチャート表示方法をサポートするために、元の設計計画を以下の図に示します。
次のコードスニペットは、chartdisplayクラスのディスプレイ()メソッドに存在します。
...... if(type.equals( "pie")){piechart chart = new piechart(); chart.display(); } else if(type.equals( "bar")){barchart chart = new barChart(); chart.display(); } ......このコードでは、LineChartなどの新しいチャートクラスを追加する必要がある場合は、ChartDisplayクラスのDisplay()メソッドのソースコードを変更し、開閉の原則に違反する新しい判断ロジックを追加する必要があります。
システムは、開閉の原則に適合させるように再構成されています。
この例では、各チャートクラスはChartDisplayクラスのDisplay()メソッドでプログラムされているため、新しいチャートクラスを追加すると、ソースコードを変更する必要があります。システムを抽象的な方法でリファクタリングできるため、新しいチャートクラスを追加するときに、開閉の原則を満たすソースコードを変更する必要はありません。特定の方法は次のとおりです。
(1)抽象チャートクラスの要約チャートを追加し、さまざまなコンクリートチャートクラスをサブクラスとして使用します。
(2)ChartDisplayクラスは抽象チャートクラス用にプログラムされており、クライアントは使用する特定のチャートを決定します。
再構築後の構造を以下の図に示します。
図2では、抽象チャートクラスの要約チャートを紹介し、ChartDisplayが抽象チャートクラス用にプログラムされており、クライアントはSetChart()メソッドを介してインスタンス化された特定のチャートオブジェクトを設定します。 display()chartdisplayの方法では、チャートオブジェクトのディスプレイ()メソッドが呼び出され、チャートが表示されます。 LineChartなどの新しいチャートを追加する必要がある場合は、LineChartをAbstractChartのサブクラスとして使用し、LineChartオブジェクトを既存のクラスライブラリのソースコードを変更せずにChartDisplayに挿入するだけです。
注:XMLやプロパティなどの形式の構成ファイルはプレーンテキストファイルであるため、コンパイルなしではVIエディターまたはメモ帳を介して直接編集できます。システムが拡張時に構成ファイルの変更のみを伴い、元のJavaコードまたはC#コードが変更を加えていない場合、システムは、開閉の原則に準拠するシステムと見なすことができます。