(7)を学習デザインパターンの美しさ:なぜプログラミング・インタフェースを実装するのではなく基づいて?各クラスがインタフェースを定義することが必要なのか?

代わりにプログラムするためのベースのインターフェース。この原則は、非常に重要であり、特に、多くの場合、通常の開発に使用されているコードの品質を向上させるために非常に有効な手段です。

「インターフェイス」という言葉の原則を解釈する方法?

この原理は英語で記述されている「プログラミングの代わりのためのインタフェースに基づいて」: “Program to an interface, not an implementation”(そのようなプログラミング言語として「インターフェース」の構文に限定特定のプログラミング言語のフック、で始まらない、時間のこの原則を理解するJavaにはinterface、インタフェース構文)。第一原理に登場したこの記事1994GoF多くのプログラミング言語(などの誕生の前に、「デザインパターン」本は、Java言語)、より抽象的、一般デザインのアイデアです。

実際には、「インターフェイス」という言葉を理解することである。この原理を、理解する鍵。本質的には、「インタフェース」を「合意」または「合意」のセットは、ユーザーのへの関数プロバイダーである「機能のリスト。」特定の実装は、「インタフェース」のこの原理をコーディングした場合、「インターフェイスベースのプログラミングを実装する代わりには、」プログラミング言語インターフェースまたは抽象クラスとして理解することができます。

この原則は、コードの品質を向上させる上で非常に有効である、ということでは、この原則の適用は、あなたが不安定な露出安定したインタフェースをパッケージ化達成するために、相分離をインタフェースと実装することができますので、それがある、と述べました。ないインターフェイスをプログラムするための上流指向システム、実装に依存しない、変更を実装する場合、コードは、結合、改善されたスケーラビリティを低減するために、変更を加えることが実質的に上流のシステムを必要としないように、不安定な詳細。

別の表現の仕方「プログラミングのためではなく、ベースのインタフェースは、」この原則は、「抽象的ではなく、プログラミングの実現に基づいて」です。表現の後者の方法は、実際にはより良い、この原則を反映するように設計されています。ソフトウェア開発では、最大の課題の一つは、また、良いか悪いかのコードの設計基準のテストで刻々と変化する要求、です。より多くのトップレベルの、より抽象的な、多くのうちの特定の実装の設計の、より多くのそれは需要の将来の変化に対応するためのより多くのことができ、コードの柔軟性を高めることができます。まだ良いコード現在のニーズに対応するために、だけでなく、将来の変化の需要だけでなく、設計、およびコードのオリジナルケースデザインに損傷を与えることなく、柔軟に対応することができます。抽象的には、コードの拡張性、柔軟性、保守性、最も有効な手段の一つ改善することです。

どのようにこれらの原則は、実際の戦闘に適用されていますか?

私たちは、システムは、画像の処理や保管に関わるビジネスロジックをたくさん持っていることを前提としています。処理後の画像は、クラウド・アリにアップロードされます。コードの再利用のために、我々は、統合提供、画像記憶関連のコード・ロジックをカプセル化しAliyunImageStore、使用するシステム全体のクラス。次のように特定のコードの実装は次のとおりです。

public class AliyunImageStore {
  //...省略属性、构造函数等...
  
  public void createBucketIfNotExisting(String bucketName) {
    // ...创建bucket代码逻辑...
    // ...失败会抛出异常..
  }
  
  public String generateAccessToken() {
    // ...根据accesskey/secrectkey等生成access token
  }
  
  public String uploadToAliyun(Image image, String bucketName, String accessToken) {
    //...上传图片到阿里云...
    //...返回图片存储在阿里云上的地址(url)...
  }
  
  public Image downloadFromAliyun(String url, String accessToken) {
    //...从阿里云下载图片...
  }
}

// AliyunImageStore类的使用举例
public class ImageProcessingJob {
  private static final String BUCKET_NAME = "ai_images_bucket";
  //...省略其他无关代码...
  
  public void process() {
    Image image = ...; //处理图片,并封装为Image对象
    AliyunImageStore imageStore = new AliyunImageStore(/*省略参数*/);
    imageStore.createBucketIfNotExisting(BUCKET_NAME);
    String accessToken = imageStore.generateAccessToken();
    imagestore.uploadToAliyun(image, BUCKET_NAME, accessToken);
  }
  
}

プロセス全体をアップロードして3つのステップから構成されています作成bucket生成し、(あなたは、単に格納ディレクトリとして理解することができます)access token運ぶ、アクセス資格情報をaccess token指定し、アップロードの写真をbucketに。コードの実装は非常に簡単で、クラス定義では、いくつかの方法がとてもきれいだった、彼らと非常に明確な、一見あまり問題はありません、我々はクラウド・アリに保存されている画像のビジネスニーズを満たすことができます。

しかし、ソフトウェア開発のみ定数が変更されています。しばらくして、私たちは自作のプライベートクラウド、クラウド・アリに保存されていない写真が、自作のプライベートクラウドに保存された写真を持っています。変更のため、このようなAの需要を満たすためには、どのように我々は、コードを変更しますか?

私たちは、の店舗の写真をプライベートクラウドの再設計と実装に必要なPrivateImageStoreクラス、および内のすべての項目置き換えるためにそれを使用するAliyunImageStoreクラスオブジェクトを。この変更は、複雑、単にそれを交換し、全体のコードの変更は重要ではないが鳴りません。しかし、私たちはしばしば、「悪魔は細部である。」、と言います この文は、ソフトウェア開発に特に適用可能です。実際には、単にデザインのインプリメンテーション、およびエラーが発生しやすい「悪魔の詳細」、何を見ての多くを隠しました。

新しいPrivateImageStoreクラスメソッドは、置き換えとして多くのコードの変更の場合は、可能な限り最小限に抑えるために設計する必要があるものを達成するためにAliyunImageStore、クラスにそれを?これがあることを、私たちを必要とAliyunImageStoreして定義されているすべてのクラスpublicにメソッドをPrivateImageStore定義して、再度クラスを再実装するために、それらの各1。そして、いくつかの問題になりそう、私は次の2点をまとめました。
まず、AliyunImageStoreこのクラスは、次のようないくつかの機能という名前の実装の詳細を公開し、uploadToAliyun()そしてdownloadFromAliyun()この開発にはインターフェースがない場合、すべての後に実装の詳細を命名同僚の意識、抽象的思考、そしてそのような暴露は、驚くべきことではない特徴、我々は最初の写真は、クラウド・アリに保存されますことを検討してください。そして、我々は「でこれを呼び出すaliyunコピーし、ワードメソッド」PrivateImageStoreクラスは、明らかに不適切です。私たちは、新しいクラスの名前を変更する場合はuploadToAliyun()downloadFromAliyun()これらの方法は、それは我々がこれらの2つの方法を使用して、すべてのコードにプロジェクトを変更することを意味し、コードの変更は、素晴らしいことかもしれません。

第二に、画像がプロセスにプライベートクラウドストレージで、クラウドアリプロセスに格納され、それはまったく同じではないかもしれません。例えば、アリ雲のプロセス画像のアップロードとダウンロード、生産する必要がaccess token、プライベートクラウドが必要とされていない状態access token一方では、AliyunImageStore定義されたgenerateAccessToken()メソッドをにコピーすることはできませんPrivateImageStore真ん中、一方で、私たちが使用しAliyunImageStore、ダウンロードの写真をアップロードするための時間を、で使用されるコードgenerateAccessToken()の方法を、あなたはプライベートクラウドのアップロードとダウンロードのプロセスを変更したい場合は、コードのニーズを調整することができます。

この2つの問題というどのようにそれを解決するには?この問題を解決するための基本的な方法は、具体的には、我々はこの次の操作を行う必要があり、原則として「プログラミングベースのインターフェイスではなく、ために」従うこと、コードの準備中、ある3ポイント。

  • ネーミング機能は、任意の実装の詳細にさらされることはできません。例えば、前述のuploadToAliyun()要件を満たしていない、削除するように変更する必要がありますaliyun:のような、代わりに、より抽象的命名では、そのような言葉をupload()

  • 具体的な実装の詳細をパッケージ化します。例えば、特別なアップロードアリクラウド関連(またはダウンロード)とプロセスは、発信者にさらされるべきではありません。私たちは、アップロードしていた(またはダウンロード)プロセスパッケージは、外部のパッケージが使用するすべての(またはダウンロード)、発信者の詳細をアップロードする方法を提供します。

  • 抽象クラスのインタフェースを定義する達成するために。特定のカテゴリには、統一されたインターフェイスの定義に依存している一貫したアップロードプロトコルに従ってください。代わりにプログラムされ、特定のカテゴリの依存ユーザーインターフェース。

この考え方によると、コードをリファクタリング。次のようにコードを再構築しました:

public interface ImageStore {
  String upload(Image image, String bucketName);
  Image download(String url);
}

public class AliyunImageStore implements ImageStore {
  //...省略属性、构造函数等...

  public String upload(Image image, String bucketName) {
    createBucketIfNotExisting(bucketName);
    String accessToken = generateAccessToken();
    //...上传图片到阿里云...
    //...返回图片在阿里云上的地址(url)...
  }

  public Image download(String url) {
    String accessToken = generateAccessToken();
    //...从阿里云下载图片...
  }

  private void createBucketIfNotExisting(String bucketName) {
    // ...创建bucket...
    // ...失败会抛出异常..
  }

  private String generateAccessToken() {
    // ...根据accesskey/secrectkey等生成access token
  }
}

// 上传下载流程改变:私有云不需要支持access token
public class PrivateImageStore implements ImageStore  {
  public String upload(Image image, String bucketName) {
    createBucketIfNotExisting(bucketName);
    //...上传图片到私有云...
    //...返回图片的url...
  }

  public Image download(String url) {
    //...从私有云下载图片...
  }

  private void createBucketIfNotExisting(String bucketName) {
    // ...创建bucket...
    // ...失败会抛出异常..
  }
}

// ImageStore的使用举例
public class ImageProcessingJob {
  private static final String BUCKET_NAME = "ai_images_bucket";
  //...省略其他无关代码...
  
  public void process() {
    Image image = ...;//处理图片,并封装为Image对象
    ImageStore imageStore = new PrivateImageStore(...);
    imagestore.upload(image, BUCKET_NAME);
  }
}

また、インタフェースの定義の多くの人々は、抗希望は定義インタフェースの実装クラスを介してプッシュするとき。最初の書き込み実装クラス、そしてクラスに実装している方法を参照して、インタフェース定義にコピーします。あなたはこの考え方に従えば、それは、不十分な抽象インタフェース定義に特定の実装に依存つながる可能性があります。このインターフェースのデザインは意味がありません。しかし、あなたはよりスムーズに問題ありませんこの考え方を、感じている場合、しかし、移動が選択的で時にインターフェース定義にクラスの動きを達成するための方法は、インタフェースを移動するには、実装依存の方法に従うことではありません、などの方法。AliyunImageStoregenerateAccessToken()

要約すると、我々はソフトウェア開発を行っている、我々は抽象化、カプセル化意識、インタフェースの意識の感覚を持っている必要があります。インターフェースの定義では、任意の実装の詳細が公開されていません。インターフェイスの定義だけではなく、それを行う方法よりも、何をすべきかを示しています。また、インタフェースの設計に我々は、特定のインターフェイスを交換する時にそれを行うことができますし、インターフェイス定義を変更する必要はありませんかどうかは、そのようなインターフェースの設計共通十分かどうかを考えなければならないとき。

各クラスのインタフェースを定義する必要がありますか?

この原理を満たすために、私はそれインタフェース対応した各クラスの定義を実装する必要はありませんでしたか?開発では、任意のコードが、それを達成するためのプログラミングの完全に独立した、唯一のインターフェースに依存すべきではないでしょうか?

何かをやる、インターフェースはどこでも、開発が不要な負担につながる、各クラスに定義されたインタフェースを与える必要があり、「度」、この原則の過度の使用を強調しています。クラスインターフェイス、インターフェイスベースのプログラミングの定義であり、インターフェイス、実装が直接プログラミングというクラスを定義していないとき、私たちは基本的な基礎を量るか、または設計原理アップの誕生の初心に戻るには、そのとき、用として。限り、この原則が発生する問題を解決するために何を把握することであるとして、あなたは突然なり、前曖昧な多くの問題があります。

上記で触れたように、この原則は、実装からインタフェースの相分離は、不安定な、安定したインタフェースは、パッケージの露出を達成することです設計されています。むしろインターフェースをプログラムするための上流指向システムに、実装に依存しない拡散コードを改善するために、コード間の結合を低減するために、変更を実装する場合、コードは変更を加えることが実質的に上流のシステムを必要としないように、不安定な詳細セックス。

この観点から、それは私たちのビジネスシナリオ、機能のみの実装では、将来的には我々はインターフェイスを設計する必要がないことを他の実装に置き換えることができない場合は、必要ベースのプログラミング・インタフェースが存在しない、設計されていますその実装クラスそれを指示。

また、より多くの不安定なシステムは、より多くの我々は、コードの保守性の延長に懸命に働きます。逆に、システムが特に安定している場合、開発が完了した後、基本的にメンテナンスを必要としない、と私たちはそのスケーラビリティを必要としないこと、それは不必要な開発時間を置きます。

RECAP

1.この原理を表現する別の方法「というよりもベースのプログラミング・インタフェースの実現」、「抽象的ではなく、プログラミングの実現に基づいて。」されます 表現の後者の方法は、実際にはより良い、この原則を反映するように設計されています。当社は、ソフトウェア開発を行う、私たちは、抽象化、カプセル化意識、インタフェースの意識の感覚を持っている必要があります。特定の実装の設計から、上部、より抽象的な、コードは、柔軟性、拡張性、保守性を向上させることができます。

2.我々は、一方では、時間のインタフェースを定義する、命名される共通のに十分な、実装に依存して単語を含めることができません。インタフェースで定義されていない一方、特定の実装に依存する方法。

ブログ記事複数のプラットフォームからこの記事OpenWriteリリース!
詳細については、私のブログをクリックしてくださいムー陳

おすすめ

転載: www.cnblogs.com/muchen-li/p/11960319.html