Design-pattern-quick-guide

提供:Dev Guides
移動先:案内検索

設計パターン-概要

設計パターンは、経験豊富なオブジェクト指向ソフトウェア開発者が使用するベストプラクティスを表しています。 設計パターンは、ソフトウェア開発者がソフトウェア開発中に直面した一般的な問題の解決策です。 これらのソリューションは、かなりの期間にわたって多くのソフトウェア開発者によって試行錯誤によって取得されました。

Gang of Four(GOF)とは何ですか?

1994年に、4人の著者Erich Gamma、Richard Helm、Ralph Johnson、およびJohn Vlissidesが Design Patterns-Elements of Reusable Object-Oriented Software というタイトルの本を出版し、ソフトウェア開発におけるデザインパターンの概念を開始しました。

これらの著者は、* Gang of Four(GOF)*と総称されています。 これらの著者によると、設計パターンは主に次のオブジェクト指向設計の原則に基づいています。

  • 実装ではなくインターフェースへのプログラム
  • 継承よりもオブジェクト構成を優先する

デザインパターンの使用

デザインパターンには、ソフトウェア開発における2つの主な用途があります。

開発者向けの共通プラットフォーム

設計パターンは標準の用語を提供し、特定のシナリオに固有です。 たとえば、シングルトンデザインパターンは単一オブジェクトの使用を意味するため、単一デザインパターンに精通しているすべての開発者は単一オブジェクトを使用し、プログラムがシングルトンパターンに従っていることを互いに伝えることができます。

ベストプラクティス

設計パターンは長い間進化しており、ソフトウェア開発中に直面する特定の問題に対する最適なソリューションを提供します。 これらのパターンを学習すると、経験の浅い開発者がソフトウェア設計を簡単かつ迅速に学習するのに役立ちます。

設計パターンの種類

デザインパターンリファレンスブック*デザインパターン-再利用可能なオブジェクト指向ソフトウェアの要素*によると、23のデザインパターンがあり、3つのカテゴリに分類できます。作成パターン、構造パターン、および動作パターンです。 また、デザインパターンの別のカテゴリであるJ2EEデザインパターンについても説明します。

S.N. Pattern & Description
1 Creational PatternsThese design patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case.
2 Structural PatternsThese design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities.
3 Behavioral PatternsThese design patterns are specifically concerned with communication between objects.
4 J2EE PatternsThese design patterns are specifically concerned with the presentation tier. These patterns are identified by Sun Java Center.

デザインパターン-工場パターン

ファクトリパターンは、Javaで最も使用されているデザインパターンの1つです。 このタイプのデザインパターンは、オブジェクトを作成する最適な方法の1つであるため、作成パターンの下にあります。

Factoryパターンでは、作成ロジックをクライアントに公開せずにオブジェクトを作成し、共通のインターフェースを使用して新しく作成されたオブジェクトを参照します。

実装

_Shape_インターフェースと、_Shape_インターフェースを実装する具体的なクラスを作成します。 ファクトリクラス_ShapeFactory_は、次のステップとして定義されます。

FactoryPatternDemo、デモクラスは_ShapeFactory_を使用して_Shape_オブジェクトを取得します。 情報(CIRCLE/RECTANGLE/SQUARE)を_ShapeFactory_に渡し、必要なオブジェクトのタイプを取得します。

ファクトリーパターンUML図

ステップ1

インターフェイスを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

Rectangle.java

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

Square.java

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

Circle.java

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

ステップ3

指定された情報に基づいて具象クラスのオブジェクトを生成するファクトリを作成します。

ShapeFactory.java

public class ShapeFactory {

  //use getShape method to get object of type shape
   public 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;
   }
}

ステップ4

ファクトリを使用して、タイプなどの情報を渡すことにより、具象クラスのオブジェクトを取得します。

FactoryPatternDemo.java

public class FactoryPatternDemo {

   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();

     //get an object of Circle and call its draw method.
      Shape shape1 = shapeFactory.getShape("CIRCLE");

     //call draw method of Circle
      shape1.draw();

     //get an object of Rectangle and call its draw method.
      Shape shape2 = shapeFactory.getShape("RECTANGLE");

     //call draw method of Rectangle
      shape2.draw();

     //get an object of Square and call its draw method.
      Shape shape3 = shapeFactory.getShape("SQUARE");

     //call draw method of square
      shape3.draw();
   }
}

ステップ5

出力を確認します。

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

デザインパターン-抽象ファクトリーパターン

Abstract Factoryパターンは、他の工場を作成するスーパー工場を回避します。 この工場は工場の工場とも呼ばれます。 このタイプのデザインパターンは、オブジェクトを作成する最適な方法の1つであるため、作成パターンの下にあります。

Abstract Factoryパターンでは、インターフェイスは、クラスを明示的に指定せずに関連オブジェクトのファクトリを作成する役割を果たします。 生成された各ファクトリは、ファクトリパターンに従ってオブジェクトを提供できます。

実装

Shapeインターフェースとそれを実装する具体的なクラスを作成します。 次のステップとして、抽象ファクトリクラスAbstractFactoryを作成します。 ファクトリクラスShapeFactoryが定義され、AbstractFactoryを拡張します。 ファクトリクリエーター/ジェネレータークラスFactoryProducerが作成されます。

AbstractFactoryPatternDemo、デモクラスはFactoryProducerを使用してAbstractFactoryオブジェクトを取得します。 情報(形状のCIRCLE/RECTANGLE/SQUARE)をAbstractFactoryに渡し、必要なオブジェクトのタイプを取得します。

抽象的なファクトリパターンUML図

ステップ1

Shapesのインターフェイスを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

RoundedRectangle.java

public class RoundedRectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside RoundedRectangle::draw() method.");
   }
}

RoundedSquare.java

public class RoundedSquare implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside RoundedSquare::draw() method.");
   }
}

Rectangle.java

public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

ステップ3

Abstractクラスを作成して、NormalおよびRounded Shapeオブジェクトのファクトリを取得します。

AbstractFactory.java

public abstract class AbstractFactory {
   abstract Shape getShape(String shapeType) ;
}

ステップ4

指定された情報に基づいて具象クラスのオブジェクトを生成するために、AbstractFactoryを拡張するファクトリクラスを作成します。

ShapeFactory.java

public class ShapeFactory extends AbstractFactory {
   @Override
   public Shape getShape(String shapeType){
      if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      }else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

RoundedShapeFactory.java

public class RoundedShapeFactory extends AbstractFactory {
   @Override
   public Shape getShape(String shapeType){
      if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new RoundedRectangle();
      }else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new RoundedSquare();
      }
      return null;
   }
}

ステップ5

ファクトリージェネレーター/プロデューサークラスを作成して、Shapeなどの情報を渡すことで工場を取得します。

FactoryProducer.java

public class FactoryProducer {
   public static AbstractFactory getFactory(boolean rounded){
      if(rounded){
         return new RoundedShapeFactory();
      }else{
         return new ShapeFactory();
      }
   }
}

ステップ6

FactoryProducerを使用してAbstractFactoryを取得し、typeなどの情報を渡すことで具体的なクラスのファクトリーを取得します。

AbstractFactoryPatternDemo.java

public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
     //get shape factory
      AbstractFactory shapeFactory = FactoryProducer.getFactory(false);
     //get an object of Shape Rectangle
      Shape shape1 = shapeFactory.getShape("RECTANGLE");
     //call draw method of Shape Rectangle
      shape1.draw();
     //get an object of Shape Square
      Shape shape2 = shapeFactory.getShape("SQUARE");
     //call draw method of Shape Square
      shape2.draw();
     //get shape factory
      AbstractFactory shapeFactory1 = FactoryProducer.getFactory(true);
     //get an object of Shape Rectangle
      Shape shape3 = shapeFactory1.getShape("RECTANGLE");
     //call draw method of Shape Rectangle
      shape3.draw();
     //get an object of Shape Square
      Shape shape4 = shapeFactory1.getShape("SQUARE");
     //call draw method of Shape Square
      shape4.draw();

   }
}

ステップ7

出力を確認します。

Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside RoundedRectangle::draw() method.
Inside RoundedSquare::draw() method.

デザインパターン-シングルトンパターン

シングルトンパターンは、Javaで最も単純なデザインパターンの1つです。 このタイプのデザインパターンは、オブジェクトを作成する最適な方法の1つであるため、作成パターンの下にあります。

このパターンには、1つのオブジェクトのみが作成されるようにしつつ、オブジェクトを作成する単一のクラスが含まれます。 このクラスは、クラスのオブジェクトをインスタンス化せずに直接アクセスできる唯一のオブジェクトにアクセスする方法を提供します。

実装

_SingleObject_クラスを作成します。 _SingleObject_クラスのコンストラクターはprivateであり、静的インスタンスを持っています。

SingleObject_クラスは、静的インスタンスを外部に取得する静的メソッドを提供します。 _SingletonPatternDemo、デモクラスは_SingleObject_クラスを使用して_SingleObject_オブジェクトを取得します。

シングルトンパターンUML図

ステップ1

シングルトンクラスを作成します。

SingleObject.java

public class SingleObject {

  //create an object of SingleObject
   private static SingleObject instance = new SingleObject();

  //make the constructor private so that this class cannot be
  //instantiated
   private SingleObject(){}

  //Get the only object available
   public static SingleObject getInstance(){
      return instance;
   }

   public void showMessage(){
      System.out.println("Hello World!");
   }
}

ステップ2

シングルトンクラスから唯一のオブジェクトを取得します。

SingletonPatternDemo.java

public class SingletonPatternDemo {
   public static void main(String[] args) {

     //illegal construct
     //Compile Time Error: The constructor SingleObject() is not visible
     //SingleObject object = new SingleObject();

     //Get the only object available
      SingleObject object = SingleObject.getInstance();

     //show the message
      object.showMessage();
   }
}

ステップ3

出力を確認します。

Hello World!

デザインパターン-ビルダーパターン

Builderパターンは、単純なオブジェクトを使用し、段階的なアプローチを使用して、複雑なオブジェクトを構築します。 このタイプのデザインパターンは、オブジェクトを作成する最適な方法の1つであるため、作成パターンの下にあります。

Builderクラスは、最終オブジェクトを段階的に構築します。 このビルダーは、他のオブジェクトから独立しています。

実装

典型的な食事がハンバーガーと冷たい飲み物であるファーストフードレストランのビジネスケースを検討しました。 バーガーはベジバーガーまたはチキンバーガーのいずれかであり、ラッパーで包装されます。 冷たい飲み物はコークスまたはペプシのいずれかで、ボトルに詰められます。

ハンバーガーや冷たい飲み物などの食品を表す_Item_インターフェースと、_Item_インターフェースを実装する具象クラス、およびハンバーガーがラッパーと冷たい飲み物に詰められるように_Packing_インターフェースを実装する食品および具象クラスの包装を表す_Packing_インターフェースを作成します。ボトルとして詰められます。

次に、Item_の_ArrayList_と_MealBuilder_を持つ_Meal_クラスを作成し、_Item_を組み合わせてさまざまなタイプの_Meal_オブジェクトを構築します。 _BuilderPatternDemo、デモクラスは_MealBuilder_を使用して_Meal_を構築します。

BuilderパターンUML図

ステップ1

食料品と梱包を表すインターフェイスアイテムを作成します。

Item.java

public interface Item {
   public String name();
   public Packing packing();
   public float price();
}

Packing.java

public interface Packing {
   public String pack();
}

ステップ2

Packingインターフェースを実装する具体的なクラスを作成します。

Wrapper.java

public class Wrapper implements Packing {

   @Override
   public String pack() {
      return "Wrapper";
   }
}

Bottle.java

public class Bottle implements Packing {

   @Override
   public String pack() {
      return "Bottle";
   }
}

ステップ3

既定の機能を提供するアイテムインターフェイスを実装する抽象クラスを作成します。

Burger.java

public abstract class Burger implements Item {

   @Override
   public Packing packing() {
      return new Wrapper();
   }

   @Override
   public abstract float price();
}

ColdDrink.java

public abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
       return new Bottle();
    }

    @Override
    public abstract float price();
}

ステップ4

BurgerおよびColdDrinkクラスを拡張する具象クラスを作成します

VegBurger.java

public class VegBurger extends Burger {

   @Override
   public float price() {
      return 25.0f;
   }

   @Override
   public String name() {
      return "Veg Burger";
   }
}

ChickenBurger.java

public class ChickenBurger extends Burger {

   @Override
   public float price() {
      return 50.5f;
   }

   @Override
   public String name() {
      return "Chicken Burger";
   }
}

Coke.java

public class Coke extends ColdDrink {

   @Override
   public float price() {
      return 30.0f;
   }

   @Override
   public String name() {
      return "Coke";
   }
}

Pepsi.java

public class Pepsi extends ColdDrink {

   @Override
   public float price() {
      return 35.0f;
   }

   @Override
   public String name() {
      return "Pepsi";
   }
}

ステップ5

上記で定義されたItemオブジェクトを持つMealクラスを作成します。

Meal.java

import java.util.ArrayList;
import java.util.List;

public class Meal {
   private List<Item> items = new ArrayList<Item>();

   public void addItem(Item item){
      items.add(item);
   }

   public float getCost(){
      float cost = 0.0f;

      for (Item item : items) {
         cost += item.price();
      }
      return cost;
   }

   public void showItems(){

      for (Item item : items) {
         System.out.print("Item : " + item.name());
         System.out.print(", Packing : " + item.packing().pack());
         System.out.println(", Price : " + item.price());
      }
   }
}

ステップ6

Mealオブジェクトを作成する実際のビルダークラスであるMealBuilderクラスを作成します。

MealBuilder.java

public class MealBuilder {

   public Meal prepareVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new VegBurger());
      meal.addItem(new Coke());
      return meal;
   }

   public Meal prepareNonVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new ChickenBurger());
      meal.addItem(new Pepsi());
      return meal;
   }
}

ステップ7

BuiderPatternDemoはMealBuiderを使用して、ビルダーパターンを示します。

BuilderPatternDemo.java

public class BuilderPatternDemo {
   public static void main(String[] args) {

      MealBuilder mealBuilder = new MealBuilder();

      Meal vegMeal = mealBuilder.prepareVegMeal();
      System.out.println("Veg Meal");
      vegMeal.showItems();
      System.out.println("Total Cost: " + vegMeal.getCost());

      Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
      System.out.println("\n\nNon-Veg Meal");
      nonVegMeal.showItems();
      System.out.println("Total Cost: " + nonVegMeal.getCost());
   }
}

ステップ8

出力を確認します。

Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

デザインパターン-プロトタイプパターン

プロトタイプパターンとは、パフォーマンスを考慮しながら複製オブジェクトを作成することです。 このタイプのデザインパターンは、オブジェクトを作成する最適な方法の1つであるため、作成パターンの下にあります。

このパターンには、現在のオブジェクトのクローンを作成するように指示するプロトタイプインターフェイスの実装が含まれます。 このパターンは、オブジェクトの直接作成にコストがかかる場合に使用されます。 たとえば、高価なデータベース操作の後にオブジェクトが作成されます。 オブジェクトをキャッシュし、次のリクエストでそのクローンを返し、必要に応じてデータベースを更新して、データベース呼び出しを減らします。

実装

抽象クラス_Shape_と、_Shape_クラスを拡張する具象クラスを作成します。 クラス_ShapeCache_は、シェープオブジェクトを_Hashtable_に保存し、要求時にクローンを返す次のステップとして定義されます。

PrototypPatternDemo、デモクラスは_ShapeCache_クラスを使用して_Shape_オブジェクトを取得します。

プロトタイプパターンUML図

ステップ1

_Clonable_インターフェイスを実装する抽象クラスを作成します。

Shape.java

public abstract class Shape implements Cloneable {

   private String id;
   protected String type;

   abstract void draw();

   public String getType(){
      return type;
   }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public Object clone() {
      Object clone = null;

      try {
         clone = super.clone();

      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }

      return clone;
   }
}

ステップ2

上記のクラスを拡張する具象クラスを作成します。

Rectangle.java

public class Rectangle extends Shape {

   public Rectangle(){
     type = "Rectangle";
   }

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

Square.java

public class Square extends Shape {

   public Square(){
     type = "Square";
   }

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

Circle.java

public class Circle extends Shape {

   public Circle(){
     type = "Circle";
   }

   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

ステップ3

データベースから具体的なクラスを取得するクラスを作成し、_Hashtable_に保存します。

ShapeCache.java

import java.util.Hashtable;

public class ShapeCache {

   private static Hashtable<String, Shape> shapeMap  = new Hashtable<String, Shape>();

   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }

  //for each shape run database query and create shape
  //shapeMap.put(shapeKey, shape);
  //for example, we are adding three shapes

   public static void loadCache() {
      Circle circle = new Circle();
      circle.setId("1");
      shapeMap.put(circle.getId(),circle);

      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);

      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(), rectangle);
   }
}

ステップ4

_PrototypePatternDemo_は、_ShapeCache_クラスを使用して、_Hashtable_に格納されている形状のクローンを取得します。

PrototypePatternDemo.java

public class PrototypePatternDemo {
   public static void main(String[] args) {
      ShapeCache.loadCache();

      Shape clonedShape = (Shape) ShapeCache.getShape("1");
      System.out.println("Shape : " + clonedShape.getType());

      Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
      System.out.println("Shape : " + clonedShape2.getType());

      Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
      System.out.println("Shape : " + clonedShape3.getType());
   }
}

ステップ5

出力を確認します。

Shape : Circle
Shape : Square
Shape : Rectangle

デザインパターン-アダプターパターン

アダプタパターンは、2つの互換性のないインターフェイス間のブリッジとして機能します。 このタイプの設計パターンは、2つの独立したインターフェースの機能を組み合わせた構造パターンの下にあります。

このパターンには、独立または互換性のないインターフェイスの機能を結合する単一のクラスが含まれます。 実際の例としては、メモリカードとラップトップ間のアダプタとして機能するカードリーダーの場合があります。 メモリカードをカードリーダーに差し込み、カードリーダーをラップトップに差し込み、ラップトップ経由でメモリカードを読み取れるようにします。

次の例では、オーディオプレーヤーデバイスはmp3ファイルのみを再生でき、vlcおよびmp4ファイルを再生できる高度なオーディオプレーヤーを使用するアダプターパターンの使用を示しています。

実装

_MediaPlayer_インターフェースと、_MediaPlayer_インターフェースを実装する具象クラス_AudioPlayer_があります。 _AudioPlayer_は、デフォルトでmp3形式のオーディオファイルを再生できます。

別のインターフェース_AdvancedMediaPlayer_と、_AdvancedMediaPlayer_インターフェースを実装する具象クラスがあります。 これらのクラスは、vlcおよびmp4形式のファイルを再生できます。

_AudioPlayer_を作成して、他の形式も再生できるようにします。 これを実現するために、_MediaPlayer_インターフェイスを実装し、_AdvancedMediaPlayer_オブジェクトを使用して必要な形式を再生するアダプタークラス_MediaAdapter_を作成しました。

_AudioPlayer_は、アダプタークラス_MediaAdapter_を使用して、目的の形式を再生できる実際のクラスを認識せずに、目的のオーディオタイプを渡します。 デモクラス_AdapterPatternDemo_は、_AudioPlayer_クラスを使用してさまざまな形式を再生します。

アダプターパターンUML図

ステップ1

Media PlayerおよびAdvanced Media Playerのインターフェイスを作成します。

MediaPlayer.java

public interface MediaPlayer {
   public void play(String audioType, String fileName);
}

AdvancedMediaPlayer.java

public interface AdvancedMediaPlayer {
   public void playVlc(String fileName);
   public void playMp4(String fileName);
}

ステップ2

_AdvancedMediaPlayer_インターフェイスを実装する具体的なクラスを作成します。

VlcPlayer.java

public class VlcPlayer implements AdvancedMediaPlayer{
   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);
   }

   @Override
   public void playMp4(String fileName) {
     //do nothing
   }
}

Mp4Player.java

public class Mp4Player implements AdvancedMediaPlayer{

   @Override
   public void playVlc(String fileName) {
     //do nothing
   }

   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);
   }
}

ステップ3

_MediaPlayer_インターフェイスを実装するアダプタークラスを作成します。

MediaAdapter.java

public class MediaAdapter implements MediaPlayer {

   AdvancedMediaPlayer advancedMusicPlayer;

   public MediaAdapter(String audioType){

      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();

      }else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }
   }

   @Override
   public void play(String audioType, String fileName) {

      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }
      else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

ステップ4

_MediaPlayer_インターフェイスを実装する具体的なクラスを作成します。

AudioPlayer.java

public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter;

   @Override
   public void play(String audioType, String fileName) {

     //inbuilt support to play mp3 music files
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: " + fileName);
      }

     //mediaAdapter is providing support to play other file formats
      else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }

      else{
         System.out.println("Invalid media. " + audioType + " format not supported");
      }
   }
}

ステップ5

AudioPlayerを使用して、さまざまな種類のオーディオ形式を再生します。

AdapterPatternDemo.java

public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();

      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}

ステップ6

出力を確認します。

Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

デザインパターン-ブリッジパターン

ブリッジは、その実装から抽象化を分離する必要がある場合に使用されます。これにより、2つを独立して変更できます。 このパターンは、実装クラスと抽象クラスの間にブリッジ構造を提供することでそれらを分離するため、このタイプの設計パターンは構造的パターンの下にあります。

このパターンには、具体的なクラスの機能をインターフェイス実装クラスから独立させるブリッジとして機能するインターフェイスが含まれます。 両方のタイプのクラスは、互いに影響を与えることなく構造的に変更できます。

次の例では、同じ抽象クラスメソッドを使用して異なるブリッジ実装クラスを使用して円を異なる色で描画できるブリッジパターンの使用方法を示しています。

実装

ブリッジの実装者として機能する_DrawAPI_インターフェイスと、DrawAPI_インターフェイスを実装する具象クラス_RedCircle _、 GreenCircle_があります。 _Shape_は抽象クラスであり、_DrawAPI_のオブジェクトを使用します。 デモクラス_BridgePatternDemo_は、_Shape_クラスを使用して異なる色の円を描画します。

ブリッジパターンUML図

ステップ1

ブリッジ実装インターフェースを作成します。

DrawAPI.java

public interface DrawAPI {
   public void drawCircle(int radius, int x, int y);
}

ステップ2

_DrawAPI_インターフェイスを実装する具体的なブリッジ実装クラスを作成します。

RedCircle.java

public class RedCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", " + y + "]");
   }
}

GreenCircle.java

public class GreenCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {
      System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", " + y + "]");
   }
}

ステップ3

_DrawAPI_インターフェイスを使用して、抽象クラス_Shape_を作成します。

Shape.java

public abstract class Shape {
   protected DrawAPI drawAPI;

   protected Shape(DrawAPI drawAPI){
      this.drawAPI = drawAPI;
   }
   public abstract void draw();
}

ステップ4

_Shape_インターフェイスを実装する具体的なクラスを作成します。

Circle.java

public class Circle extends Shape {
   private int x, y, radius;

   public Circle(int x, int y, int radius, DrawAPI drawAPI) {
      super(drawAPI);
      this.x = x;
      this.y = y;
      this.radius = radius;
   }

   public void draw() {
      drawAPI.drawCircle(radius,x,y);
   }
}

ステップ5

_Shape_および_DrawAPI_クラスを使用して、異なる色の円を描きます。

BridgePatternDemo.java

public class BridgePatternDemo {
   public static void main(String[] args) {
      Shape redCircle = new Circle(100,100, 10, new RedCircle());
      Shape greenCircle = new Circle(100,100, 10, new GreenCircle());

      redCircle.draw();
      greenCircle.draw();
   }
}

ステップ6

出力を確認します。

Drawing Circle[ color: red, radius: 10, x: 100, 100]
Drawing Circle[  color: green, radius: 10, x: 100, 100]

デザインパターン-フィルターパターン

フィルターパターンまたは基準パターンは、さまざまな基準を使用して一連のオブジェクトをフィルター処理し、論理演算を通じて切り離された方法でチェーンすることを可能にする設計パターンです。 このタイプの設計パターンは、複数の基準を組み合わせて単一の基準を取得するため、構造パターンの下にあります。

実装

_Person_オブジェクト、_Criteria_インターフェイス、およびこのインターフェイスを実装する具象クラスを作成して、_Person_オブジェクトのリストをフィルター処理します。 デモクラス_CriteriaPatternDemo_は、_Criteria_オブジェクトを使用して、さまざまな基準とその組み合わせに基づいて_Person_オブジェクトのリストをフィルター処理します。

フィルターパターンUML図

ステップ1

基準が適用されるクラスを作成します。

Person.java

public class Person {

   private String name;
   private String gender;
   private String maritalStatus;

   public Person(String name, String gender, String maritalStatus){
      this.name = name;
      this.gender = gender;
      this.maritalStatus = maritalStatus;
   }

   public String getName() {
      return name;
   }
   public String getGender() {
      return gender;
   }
   public String getMaritalStatus() {
      return maritalStatus;
   }
}

ステップ2

Criteriaのインターフェイスを作成します。

Criteria.java

import java.util.List;

public interface Criteria {
   public List<Person> meetCriteria(List<Person> persons);
}

ステップ3

_Criteria_インターフェースを実装する具象クラスを作成します。

CriteriaMale.java

import java.util.ArrayList;
import java.util.List;

public class CriteriaMale implements Criteria {

   @Override
   public List<Person> meetCriteria(List<Person> persons) {
      List<Person> malePersons = new ArrayList<Person>();

      for (Person person : persons) {
         if(person.getGender().equalsIgnoreCase("MALE")){
            malePersons.add(person);
         }
      }
      return malePersons;
   }
}

CriteriaFemale.java

import java.util.ArrayList;
import java.util.List;

public class CriteriaFemale implements Criteria {

   @Override
   public List<Person> meetCriteria(List<Person> persons) {
      List<Person> femalePersons = new ArrayList<Person>();

      for (Person person : persons) {
         if(person.getGender().equalsIgnoreCase("FEMALE")){
            femalePersons.add(person);
         }
      }
      return femalePersons;
   }
}

CriteriaSingle.java

import java.util.ArrayList;
import java.util.List;

public class CriteriaSingle implements Criteria {

   @Override
   public List<Person> meetCriteria(List<Person> persons) {
      List<Person> singlePersons = new ArrayList<Person>();

      for (Person person : persons) {
         if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){
            singlePersons.add(person);
         }
      }
      return singlePersons;
   }
}

AndCriteria.java

import java.util.List;

public class AndCriteria implements Criteria {

   private Criteria criteria;
   private Criteria otherCriteria;

   public AndCriteria(Criteria criteria, Criteria otherCriteria) {
      this.criteria = criteria;
      this.otherCriteria = otherCriteria;
   }

   @Override
   public List<Person> meetCriteria(List<Person> persons) {

      List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
      return otherCriteria.meetCriteria(firstCriteriaPersons);
   }
}

OrCriteria.java

import java.util.List;

public class OrCriteria implements Criteria {

   private Criteria criteria;
   private Criteria otherCriteria;

   public OrCriteria(Criteria criteria, Criteria otherCriteria) {
      this.criteria = criteria;
      this.otherCriteria = otherCriteria;
   }

   @Override
   public List<Person> meetCriteria(List<Person> persons) {
      List<Person> firstCriteriaItems = criteria.meetCriteria(persons);
      List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons);

      for (Person person : otherCriteriaItems) {
         if(!firstCriteriaItems.contains(person)){
            firstCriteriaItems.add(person);
         }
      }
      return firstCriteriaItems;
   }
}

ステップ4

さまざまな基準とその組み合わせを使用して、人を除外します。

CriteriaPatternDemo.java

import java.util.ArrayList;
import java.util.List;

public class CriteriaPatternDemo {
   public static void main(String[] args) {
      List<Person> persons = new ArrayList<Person>();

      persons.add(new Person("Robert","Male", "Single"));
      persons.add(new Person("John", "Male", "Married"));
      persons.add(new Person("Laura", "Female", "Married"));
      persons.add(new Person("Diana", "Female", "Single"));
      persons.add(new Person("Mike", "Male", "Single"));
      persons.add(new Person("Bobby", "Male", "Single"));

      Criteria male = new CriteriaMale();
      Criteria female = new CriteriaFemale();
      Criteria single = new CriteriaSingle();
      Criteria singleMale = new AndCriteria(single, male);
      Criteria singleOrFemale = new OrCriteria(single, female);

      System.out.println("Males: ");
      printPersons(male.meetCriteria(persons));

      System.out.println("\nFemales: ");
      printPersons(female.meetCriteria(persons));

      System.out.println("\nSingle Males: ");
      printPersons(singleMale.meetCriteria(persons));

      System.out.println("\nSingle Or Females: ");
      printPersons(singleOrFemale.meetCriteria(persons));
   }

   public static void printPersons(List<Person> persons){

      for (Person person : persons) {
         System.out.println("Person : [ Name : " + person.getName() + ", Gender : " + person.getGender() + ", Marital Status : " + person.getMaritalStatus() + " ]");
      }
   }
}

ステップ5

出力を確認します。

Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Females:
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]

Single Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Single Or Females:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]

デザインパターン-複合パターン

複合パターンは、オブジェクトのグループを単一のオブジェクトとして同様に扱う必要がある場合に使用されます。 複合パターンは、階層構造だけでなく部分も表すために、ツリー構造でオブジェクトを構成します。 このパターンのパターンは、オブジェクトのグループのツリー構造を作成するため、構造パターンの下にあります。

このパターンは、独自のオブジェクトのグループを含むクラスを作成します。 このクラスは、同じオブジェクトのグループを変更する方法を提供します。

組織の従業員階層を示す次の例で、複合パターンの使用を示しています。

実装

複合パターンアクタークラスとして機能するクラス_Employee_があります。 デモクラス_CompositePatternDemo_は、_Employee_クラスを使用して部門レベルの階層を追加し、すべての従業員を印刷します。

複合パターンUML図

ステップ1

_Employee_オブジェクトのリストを持つ_Employee_クラスを作成します。

Employee.java

import java.util.ArrayList;
import java.util.List;

public class Employee {
   private String name;
   private String dept;
   private int salary;
   private List<Employee> subordinates;

  //constructor
   public Employee(String name,String dept, int sal) {
      this.name = name;
      this.dept = dept;
      this.salary = sal;
      subordinates = new ArrayList<Employee>();
   }

   public void add(Employee e) {
      subordinates.add(e);
   }

   public void remove(Employee e) {
      subordinates.remove(e);
   }

   public List<Employee> getSubordinates(){
     return subordinates;
   }

   public String toString(){
      return ("Employee :[ Name : " + name + ", dept : " + dept + ", salary :" + salary+" ]");
   }
}

ステップ2

_Employee_クラスを使用して、従業員階層を作成および印刷します。

CompositePatternDemo.java

public class CompositePatternDemo {
   public static void main(String[] args) {

      Employee CEO = new Employee("John","CEO", 30000);

      Employee headSales = new Employee("Robert","Head Sales", 20000);

      Employee headMarketing = new Employee("Michel","Head Marketing", 20000);

      Employee clerk1 = new Employee("Laura","Marketing", 10000);
      Employee clerk2 = new Employee("Bob","Marketing", 10000);

      Employee salesExecutive1 = new Employee("Richard","Sales", 10000);
      Employee salesExecutive2 = new Employee("Rob","Sales", 10000);

      CEO.add(headSales);
      CEO.add(headMarketing);

      headSales.add(salesExecutive1);
      headSales.add(salesExecutive2);

      headMarketing.add(clerk1);
      headMarketing.add(clerk2);

     //print all employees of the organization
      System.out.println(CEO);

      for (Employee headEmployee : CEO.getSubordinates()) {
         System.out.println(headEmployee);

         for (Employee employee : headEmployee.getSubordinates()) {
            System.out.println(employee);
         }
      }
   }
}

ステップ3

出力を確認します。

Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]

デザインパターン-デコレータパターン

デコレータパターンを使用すると、ユーザーは既存のオブジェクトの構造を変更せずに、新しい機能を追加できます。 このタイプのデザインパターンは、既存のクラスのラッパーとして機能するため、構造パターンの下にあります。

このパターンは、元のクラスをラップするデコレータークラスを作成し、クラスメソッドシグネチャをそのまま保持する追加機能を提供します。

シェイプクラスを変更せずに、ある色でシェイプを装飾する次の例で、デコレータパターンの使用を示しています。

実装

_Shape_インターフェースと、_Shape_インターフェースを実装する具体的なクラスを作成します。 次に、_Shape_インターフェイスを実装し、_Shape_オブジェクトをインスタンス変数として持つ抽象デコレータクラス_ShapeDecorator_を作成します。

_RedShapeDecorator_は、_ShapeDecorator_を実装する具象クラスです。

デモクラス_DecoratorPatternDemo_は、_RedShapeDecorator_を使用して_Shape_オブジェクトを装飾します。

装飾パターンUML図

ステップ1

インターフェイスを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

Rectangle.java

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

Circle.java

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Shape: Circle");
   }
}

ステップ3

_Shape_インターフェイスを実装する抽象デコレータクラスを作成します。

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;

   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }

   public void draw(){
      decoratedShape.draw();
   }
}

ステップ4

_ShapeDecorator_クラスを拡張する具体的なデコレータクラスを作成します。

RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);
   }

   @Override
   public void draw() {
      decoratedShape.draw();
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

ステップ5

_RedShapeDecorator_を使用して、_Shape_オブジェクトを装飾します。

DecoratorPatternDemo.java

public class DecoratorPatternDemo {
   public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();

      System.out.println("\nCircle of red border");
      redCircle.draw();

      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}

ステップ6

出力を確認します。

Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red

デザインパターン-ファサードパターン

ファサードパターンは、システムの複雑さを隠し、クライアントがシステムにアクセスできるクライアントへのインターフェイスを提供します。 このタイプのデザインパターンは、複雑さを隠すために既存のシステムにインターフェイスを追加するため、構造パターンの下にあります。

このパターンには、クライアントが必要とする単純化されたメソッドを提供する単一のクラスが含まれ、既存のシステムクラスのメソッドへの呼び出しを委任します。

実装

_Shape_インターフェイスと、_Shape_インターフェイスを実装する具体的なクラスを作成します。 ファサードクラス_ShapeMaker_は、次のステップとして定義されます。

_ShapeMaker_クラスは、具象クラスを使用して、ユーザー呼び出しをこれらのクラスに委任します。 デモクラス_FacadePatternDemo_は、_ShapeMaker_クラスを使用して結果を表示します。

ファサードパターンUML図

ステップ1

インターフェイスを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

Rectangle.java

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}

Square.java

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}

Circle.java

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}

ステップ3

ファサードクラスを作成します。

ShapeMaker.java

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

ステップ4

ファサードを使用して、さまざまな種類の図形を描画します。

FacadePatternDemo.java

public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();

      shapeMaker.drawCircle();
      shapeMaker.drawRectangle();
      shapeMaker.drawSquare();
   }
}

ステップ5

出力を確認します。

Circle::draw()
Rectangle::draw()
Square::draw()

デザインパターン-フライウェイトパターン

フライウェイトパターンは、主に作成されるオブジェクトの数を減らし、メモリフットプリントを減らしてパフォーマンスを向上させるために使用されます。 このタイプの設計パターンは、オブジェクトの数を減らしてアプリケーションのオブジェクト構造を改善する方法を提供するため、構造パターンの下にあります。

Flyweightパターンは、既存の類似の種類のオブジェクトを保存して再利用しようとし、一致するオブジェクトが見つからない場合は新しいオブジェクトを作成します。 さまざまな場所に20の円を描くことでこのパターンを示しますが、作成するオブジェクトは5つだけです。 使用できる色は5色のみなので、既存の_Circle_オブジェクトを確認するために色プロパティが使用されます。

実装

_Shape_インターフェースと、_Shape_インターフェースを実装する具象クラス_Circle_を作成します。 ファクトリクラス_ShapeFactory_は、次のステップとして定義されます。

_ShapeFactory_には、_Circle_オブジェクトの色としてキーを持つ_Circle_の_HashMap_があります。 _ShapeFactory_に特定の色の円を作成する要求が来るたびに、_Cashcle_のオブジェクトが見つかった場合はそのオブジェクトが返され、それ以外の場合はそのオブジェクトが返されます。クライアント。

デモクラス_FlyWeightPatternDemo_は、ShapeFactory_を使用して_Shape_オブジェクトを取得します。 情報(_red/green/blue/black/white)を_ShapeFactory_に渡し、必要な色の円を取得します。

フライウェイトパターンUML図

ステップ1

インターフェイスを作成します。

Shape.java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェイスを実装する具象クラスを作成します。

Circle.java

public class Circle implements Shape {
   private String color;
   private int x;
   private int y;
   private int radius;

   public Circle(String color){
      this.color = color;
   }

   public void setX(int x) {
      this.x = x;
   }

   public void setY(int y) {
      this.y = y;
   }

   public void setRadius(int radius) {
      this.radius = radius;
   }

   @Override
   public void draw() {
      System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius);
   }
}

ステップ3

ファクトリを作成して、指定された情報に基づいて具象クラスのオブジェクトを生成します。

ShapeFactory.java

import java.util.HashMap;

public class ShapeFactory {

  //Uncomment the compiler directive line and
  //javac *.java will compile properly.
  //@SuppressWarnings("unchecked")
   private static final HashMap circleMap = new HashMap();

   public static Shape getCircle(String color) {
      Circle circle = (Circle)circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("Creating circle of color : " + color);
      }
      return circle;
   }
}

ステップ4

ファクトリを使用して、色などの情報を渡すことにより、具体的なクラスのオブジェクトを取得します。

FlyweightPatternDemo.java

public class FlyweightPatternDemo {
   private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" };
   public static void main(String[] args) {

      for(int i=0; i < 20; ++i) {
         Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
         circle.setX(getRandomX());
         circle.setY(getRandomY());
         circle.setRadius(100);
         circle.draw();
      }
   }
   private static String getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
   private static int getRandomX() {
      return (int)(Math.random()*100 );
   }
   private static int getRandomY() {
      return (int)(Math.random()*100);
   }
}

ステップ5

出力を確認します。

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100

デザインパターン-プロキシパターン

プロキシパターンでは、クラスは別のクラスの機能を表します。 このタイプの設計パターンは、構造的パターンの下にあります。

プロキシパターンでは、元のオブジェクトを持つオブジェクトを作成して、その機能を外界にインターフェースします。

実装

_Image_インターフェースと、_Image_インターフェースを実装する具体的なクラスを作成します。 _ProxyImage_は、_RealImage_オブジェクトの読み込みのメモリフットプリントを削減するためのプロキシクラスです。

デモクラス_ProxyPatternDemo_は、_ProxyImage_を使用して、必要に応じて_Image_オブジェクトをロードおよび表示します。

プロキシパターンUML図

ステップ1

インターフェイスを作成します。

Image.java

public interface Image {
   void display();
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

RealImage.java

public class RealImage implements Image {

   private String fileName;

   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }

   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }

   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}

ProxyImage.java

public class ProxyImage implements Image{

   private RealImage realImage;
   private String fileName;

   public ProxyImage(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

ステップ3

必要に応じて、_ProxyImage_を使用して_RealImage_クラスのオブジェクトを取得します。

ProxyPatternDemo.java

public class ProxyPatternDemo {

   public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");

     //image will be loaded from disk
      image.display();
      System.out.println("");

     //image will not be loaded from disk
      image.display();
   }
}

ステップ4

出力を確認します。

Loading test_10mb.jpg
Displaying test_10mb.jpg

Displaying test_10mb.jpg

責任の連鎖パターン

名前が示すように、責任の連鎖パターンは、要求の受信者オブジェクトの連鎖を作成します。 このパターンは、リクエストのタイプに基づいてリクエストの送信者と受信者を分離します。 このパターンは行動パターンの下にあります。

このパターンでは、通常、各レシーバーには別のレシーバーへの参照が含まれます。 1つのオブジェクトが要求を処理できない場合、同じオブジェクトを次の受信者に渡します。

実装

ロギングのレベルを持つ抽象クラス_AbstractLogger_を作成しました。 次に、_AbstractLogger_を拡張する3種類のロガーを作成しました。 各ロガーはメッセージのレベルをそのレベルまでチェックし、それに応じて印刷します。そうでない場合、メッセージを印刷して次のロガーに渡しません。

責任パターンUMLダイアグラムのチェーン

ステップ1

抽象ロガークラスを作成します。

AbstractLogger.java

public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;

   protected int level;

  //next element in chain or responsibility
   protected AbstractLogger nextLogger;

   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }

   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }

   abstract protected void write(String message);

}

ステップ2

ロガーを拡張する具象クラスを作成します。

ConsoleLogger.java

public class ConsoleLogger extends AbstractLogger {

   public ConsoleLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {
      System.out.println("Standard Console::Logger: " + message);
   }
}

ErrorLogger.java

public class ErrorLogger extends AbstractLogger {

   public ErrorLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {
      System.out.println("Error Console::Logger: " + message);
   }
}

FileLogger.java

public class FileLogger extends AbstractLogger {

   public FileLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {
      System.out.println("File::Logger: " + message);
   }
}

ステップ3

さまざまなタイプのロガーを作成します。 それらにエラーレベルを割り当て、各ロガーで次のロガーを設定します。 各ロガーの次のロガーは、チェーンの一部を表します。

ChainPatternDemo.java

public class ChainPatternDemo {

   private static AbstractLogger getChainOfLoggers(){

      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);

      return errorLogger;
   }

   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();

      loggerChain.logMessage(AbstractLogger.INFO,
         "This is an information.");

      loggerChain.logMessage(AbstractLogger.DEBUG,
         "This is an debug level information.");

      loggerChain.logMessage(AbstractLogger.ERROR,
         "This is an error information.");
   }
}

ステップ4

出力を確認します。

Standard Console::Logger: This is an information.
File::Logger: This is an debug level information.
Standard Console::Logger: This is an debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

デザインパターン-コマンドパターン

コマンドパターンはデータ駆動型のデザインパターンであり、動作パターンカテゴリに分類されます。 要求は、コマンドとしてオブジェクトの下にラップされ、呼び出し側オブジェクトに渡されます。 呼び出し側オブジェクトは、このコマンドを処理できる適切なオブジェクトを探し、コマンドを実行する対応するオブジェクトにコマンドを渡します。

実装

コマンドとして機能するインターフェース_Order_を作成しました。 リクエストとして機能する_Stock_クラスを作成しました。 実際のコマンド処理を実行する_Order_インターフェイスを実装する具体的なコマンドクラス_BuyStock_および_SellStock_があります。 呼び出し元オブジェクトとして機能するクラス_Broker_が作成されます。 注文を受けて注文することができます。

_Broker_オブジェクトはコマンドパターンを使用して、コマンドのタイプに基づいて、どのオブジェクトがどのコマンドを実行するかを識別します。 デモクラス_CommandPatternDemo_は、_Broker_クラスを使用してコマンドパターンを示します。

コマンドパターンUML図

ステップ1

コマンドインターフェイスを作成します。

Order.java

public interface Order {
   void execute();
}

ステップ2

要求クラスを作成します。

Stock.java

public class Stock {

   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+",
         Quantity: " + quantity +" ] sold");
   }
}

ステップ3

_Order_インターフェイスを実装する具体的なクラスを作成します。

BuyStock.java

public class BuyStock implements Order {
   private Stock abcStock;

   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.buy();
   }
}

SellStock.java

public class SellStock implements Order {
   private Stock abcStock;

   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   public void execute() {
      abcStock.sell();
   }
}

ステップ4

コマンド呼び出しクラスを作成します。

Broker.java

import java.util.ArrayList;
import java.util.List;

   public class Broker {
   private List<Order> orderList = new ArrayList<Order>();

   public void takeOrder(Order order){
      orderList.add(order);
   }

   public void placeOrders(){

      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}

ステップ5

Brokerクラスを使用して、コマンドを取得および実行します。

CommandPatternDemo.java

public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();

      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);

      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);

      broker.placeOrders();
   }
}

ステップ6

出力を確認します。

Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold

デザインパターン-通訳パターン

通訳パターンは、言語の文法または表現を評価する方法を提供します。 このタイプのパターンは、行動パターンの下にあります。 このパターンには、特定のコンテキストの解釈を指示する式インターフェースの実装が含まれます。 このパターンは、SQL解析、シンボル処理エンジンなどで使用されます。

実装

Expression_インターフェイスと、_Expression_インターフェイスを実装する具体的なクラスを作成します。 問題のコンテキストのメインインタープリターとして機能するクラス_TerminalExpression_が定義されています。 他のクラス_OrExpression _、 AndExpression_は、組み合わせ式の作成に使用されます。

デモクラスである_InterpreterPatternDemo_は、_Expression_クラスを使用してルールを作成し、式の解析を実証します。

インタープリターパターンUML図

ステップ1

式インターフェイスを作成します。

Expression.java

public interface Expression {
   public boolean interpret(String context);
}

ステップ2

上記のインターフェースを実装する具体的なクラスを作成します。

TerminalExpression.java

public class TerminalExpression implements Expression {

   private String data;

   public TerminalExpression(String data){
      this.data = data;
   }

   @Override
   public boolean interpret(String context) {

      if(context.contains(data)){
         return true;
      }
      return false;
   }
}

OrExpression.java

public class OrExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public OrExpression(Expression expr1, Expression expr2) {
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {
      return expr1.interpret(context) || expr2.interpret(context);
   }
}

AndExpression.java

public class AndExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public AndExpression(Expression expr1, Expression expr2) {
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {
      return expr1.interpret(context) && expr2.interpret(context);
   }
}

ステップ3

_InterpreterPatternDemo_は、_Expression_クラスを使用してルールを作成し、解析します。

InterpreterPatternDemo.java

public class InterpreterPatternDemo {

  //Rule: Robert and John are male
   public static Expression getMaleExpression(){
      Expression robert = new TerminalExpression("Robert");
      Expression john = new TerminalExpression("John");
      return new OrExpression(robert, john);
   }

  //Rule: Julie is a married women
   public static Expression getMarriedWomanExpression(){
      Expression julie = new TerminalExpression("Julie");
      Expression married = new TerminalExpression("Married");
      return new AndExpression(julie, married);
   }

   public static void main(String[] args) {
      Expression isMale = getMaleExpression();
      Expression isMarriedWoman = getMarriedWomanExpression();

      System.out.println("John is male? " + isMale.interpret("John"));
      System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));
   }
}

ステップ4

出力を確認します。

John is male? true
Julie is a married women? true

デザインパターン-イテレータパターン

イテレータパターンは、Javaおよび.Netプログラミング環境で非常に一般的に使用されるデザインパターンです。 このパターンは、基礎となる表現を知る必要なく、コレクションオブジェクトの要素にシーケンシャルにアクセスする方法を取得するために使用されます。

イテレータパターンは、動作パターンカテゴリに分類されます。

実装

ナビゲーションメソッドをナレーションする_Iterator_インターフェイスと、イテレータを再実行する_Container_インターフェイスを作成します。 _Container_インターフェースを実装する具体的なクラスは、_Iterator_インターフェースを実装して使用する責任があります。

デモクラス_IteratorPatternDemo_は、_NamesRepository_にコレクションとして保存されている_Names_を印刷するための具体的なクラス実装である_NamesRepository_を使用します。

イテレーターパターンUML図

ステップ1

インターフェイスを作成します。

Iterator.java

public interface Iterator {
   public boolean hasNext();
   public Object next();
}

Container.java

public interface Container {
   public Iterator getIterator();
}

ステップ2

_Container_インターフェースを実装する具象クラスを作成します。 このクラスには、_Iterator_インターフェイスを実装する内部クラス_NameIterator_があります。

NameRepository.java

public class NameRepository implements Container {
   public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};

   @Override
   public Iterator getIterator() {
      return new NameIterator();
   }

   private class NameIterator implements Iterator {

      int index;

      @Override
      public boolean hasNext() {

         if(index < names.length){
            return true;
         }
         return false;
      }

      @Override
      public Object next() {

         if(this.hasNext()){
            return names[index++];
         }
         return null;
      }
   }
}

ステップ3

_NameRepository_を使用して、イテレータを取得し、名前を出力します。

IteratorPatternDemo.java

public class IteratorPatternDemo {

   public static void main(String[] args) {
      NameRepository namesRepository = new NameRepository();

      for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){
         String name = (String)iter.next();
         System.out.println("Name : " + name);
      }
   }
}

ステップ4

出力を確認します。

Name : Robert
Name : John
Name : Julie
Name : Lora

デザインパターン-メディエーターパターン

メディエーターパターンは、複数のオブジェクトまたはクラス間の通信の複雑さを軽減するために使用されます。 このパターンは、通常、異なるクラス間のすべての通信を処理し、疎結合によるコードの簡単なメンテナンスをサポートするメディエータークラスを提供します。 メディエーターパターンは、行動パターンカテゴリに分類されます。

実装

複数のユーザーがメッセージをチャットルームに送信できるチャットルームを例に、メディエーターパターンを示しています。すべてのユーザーにメッセージを表示するのはチャットルームの責任です。 2つのクラス_ChatRoom_および_User_を作成しました。 _User_オブジェクトは、_ChatRoom_メソッドを使用してメッセージを共有します。

デモクラス_MediatorPatternDemo_は、_User_オブジェクトを使用して、それらの間の通信を表示します。

メディエーターパターンUML図

ステップ1

メディエータークラスを作成します。

ChatRoom.java

import java.util.Date;

public class ChatRoom {
   public static void showMessage(User user, String message){
      System.out.println(new Date().toString() + " [" + user.getName() + "] : " + message);
   }
}

ステップ2

ユーザークラスを作成する

User.java

public class User {
   private String name;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public User(String name){
      this.name  = name;
   }

   public void sendMessage(String message){
      ChatRoom.showMessage(this,message);
   }
}

ステップ3

_User_オブジェクトを使用して、それらの間の通信を示します。

MediatorPatternDemo.java

public class MediatorPatternDemo {
   public static void main(String[] args) {
      User robert = new User("Robert");
      User john = new User("John");

      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}

ステップ4

出力を確認します。

Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!

デザインパターン-Mementoパターン

Mementoパターンは、オブジェクトの状態を以前の状態に復元するために使用されます。 Mementoパターンは行動パターンのカテゴリに分類されます。

実装

Mementoパターンは3つのアクタークラスを使用します。 Mementoには、復元するオブジェクトの状態が含まれています。 オリジネーターは状態を作成してMementoオブジェクトに保存し、Caretakerオブジェクトはオブジェクトの状態をMementoから復元します。 クラス_Memento Originator_および_CareTaker_を作成しました。

デモクラス_MementoPatternDemo_は、_CareTaker_および_Originator_オブジェクトを使用して、オブジェクトの状態の復元を示します。

メメントパターンUML図

ステップ1

Mementoクラスを作成します。

Memento.java

public class Memento {
   private String state;

   public Memento(String state){
      this.state = state;
   }

   public String getState(){
      return state;
   }
}

ステップ2

Originatorクラスを作成する

Originator.java

public class Originator {
   private String state;

   public void setState(String state){
      this.state = state;
   }

   public String getState(){
      return state;
   }

   public Memento saveStateToMemento(){
      return new Memento(state);
   }

   public void getStateFromMemento(Memento memento){
      state = memento.getState();
   }
}

ステップ3

CareTakerクラスを作成する

CareTaker.java

import java.util.ArrayList;
import java.util.List;

public class CareTaker {
   private List<Memento> mementoList = new ArrayList<Memento>();

   public void add(Memento state){
      mementoList.add(state);
   }

   public Memento get(int index){
      return mementoList.get(index);
   }
}

ステップ4

_CareTaker_および_Originator_オブジェクトを使用します。

MementoPatternDemo.java

public class MementoPatternDemo {
   public static void main(String[] args) {

      Originator originator = new Originator();
      CareTaker careTaker = new CareTaker();

      originator.setState("State #1");
      originator.setState("State #2");
      careTaker.add(originator.saveStateToMemento());

      originator.setState("State #3");
      careTaker.add(originator.saveStateToMemento());

      originator.setState("State #4");
      System.out.println("Current State: " + originator.getState());

      originator.getStateFromMemento(careTaker.get(0));
      System.out.println("First saved State: " + originator.getState());
      originator.getStateFromMemento(careTaker.get(1));
      System.out.println("Second saved State: " + originator.getState());
   }
}

ステップ5

出力を確認します。

Current State: State #4
First saved State: State #2
Second saved State: State #3

デザインパターン-オブザーバーパターン

オブザーバーパターンは、1つのオブジェクトが変更された場合、その依存オブジェクトに自動的に通知されるなど、オブジェクト間に1対多の関係がある場合に使用されます。 オブザーバーパターンは行動パターンカテゴリに分類されます。

実装

Observerパターンは3つのアクタークラスを使用します。 サブジェクト、オブザーバー、クライアント。 サブジェクトは、オブザーバーをクライアントオブジェクトにアタッチおよびデタッチするメソッドを持つオブジェクトです。 抽象クラス_Observer_と、クラス_Observer_を拡張する具象クラス_Subject_を作成しました。

デモクラス_ObserverPatternDemo_は、_Subject_と具象クラスオブジェクトを使用して、実際のオブザーバーパターンを示します。

オブザーバーパターンUML図

ステップ1

Subjectクラスを作成します。

Subject.java

import java.util.ArrayList;
import java.util.List;

public class Subject {

   private List<Observer> observers = new ArrayList<Observer>();
   private int state;

   public int getState() {
      return state;
   }

   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }

   public void attach(Observer observer){
      observers.add(observer);
   }

   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }
}

ステップ2

Observerクラスを作成します。

Observer.java

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

ステップ3

具体的なオブザーバークラスを作成する

BinaryObserver.java

public class BinaryObserver extends Observer{

   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
      System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) );
   }
}

OctalObserver.java

public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
     System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) );
   }
}

HexaObserver.java

public class HexaObserver extends Observer{

   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
      System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() );
   }
}

ステップ4

_Subject_および具象オブザーバーオブジェクトを使用します。

ObserverPatternDemo.java

public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();

      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);

      System.out.println("First state change: 15");
      subject.setState(15);
      System.out.println("Second state change: 10");
      subject.setState(10);
   }
}

ステップ5

出力を確認します。

First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

デザインパターン-状態パターン

状態パターンでは、クラスの動作はその状態に基づいて変化します。 このタイプの設計パターンは、動作パターンの下にあります。

状態パターンでは、さまざまな状態を表すオブジェクトと、状態オブジェクトの変化に応じて動作が変化するコンテキストオブジェクトを作成します。

実装

アクションを定義する_State_インターフェイスと、_State_インターフェイスを実装する具象状態クラスを作成します。 _Context_は、状態を保持するクラスです。

デモクラスである_StatePatternDemo_は、_Context_および状態オブジェクトを使用して、状態のタイプに基づくコンテキストの動作の変化を示します。

状態パターンUML図

ステップ1

インターフェイスを作成します。

State.java

public interface State {
   public void doAction(Context context);
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

StartState.java

public class StartState implements State {

   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this);
   }

   public String toString(){
      return "Start State";
   }
}

StopState.java

public class StopState implements State {

   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      context.setState(this);
   }

   public String toString(){
      return "Stop State";
   }
}

ステップ3

_Context_クラスを作成します。

Context.java

public class Context {
   private State state;

   public Context(){
      state = null;
   }

   public void setState(State state){
      this.state = state;
   }

   public State getState(){
      return state;
   }
}

ステップ4

_Context_を使用して、_State_が変化したときの動作の変化を確認します。

StatePatternDemo.java

public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();

      StartState startState = new StartState();
      startState.doAction(context);

      System.out.println(context.getState().toString());

      StopState stopState = new StopState();
      stopState.doAction(context);

      System.out.println(context.getState().toString());
   }
}

ステップ5

出力を確認します。

Player is in start state
Start State
Player is in stop state
Stop State

デザインパターン-ヌルオブジェクトパターン

Null Objectパターンでは、NULLオブジェクトがNULLオブジェクトインスタンスのチェックを置き換えます。 null値のチェックを行うのではなく、Nullオブジェクトは何もしない関係を反映します。 このようなNullオブジェクトは、データが利用できない場合のデフォルトの動作を提供するためにも使用できます。

Null Objectパターンでは、実行するさまざまな操作を指定する抽象クラス、このクラスを拡張する具体的なクラス、およびこのクラスの実装を何も提供しないnullオブジェクトクラスを作成し、null値をチェックする必要がある場合は無意識に使用します。

実装

操作を定義する_AbstractCustomer_抽象クラスを作成します。 ここでは、_AbstractCustomer_クラスを拡張する顧客クラスと具象クラスの名前。 渡された顧客の名前に基づいて、_RealCustomer_または_NullCustomer_オブジェクトを返すファクトリクラス_CustomerFactory_が作成されます。

デモクラス_NullPatternDemo_は、_CustomerFactory_を使用して、Null Objectパターンの使用方法を示します。

ヌルオブジェクトパターンUML図

ステップ1

抽象クラスを作成します。

AbstractCustomer.java

public abstract class AbstractCustomer {
   protected String name;
   public abstract boolean isNil();
   public abstract String getName();
}

ステップ2

上記のクラスを拡張する具象クラスを作成します。

RealCustomer.java

public class RealCustomer extends AbstractCustomer {

   public RealCustomer(String name) {
      this.name = name;
   }

   @Override
   public String getName() {
      return name;
   }

   @Override
   public boolean isNil() {
      return false;
   }
}

NullCustomer.java

public class NullCustomer extends AbstractCustomer {

   @Override
   public String getName() {
      return "Not Available in Customer Database";
   }

   @Override
   public boolean isNil() {
      return true;
   }
}

ステップ3

_CustomerFactory_クラスを作成します。

CustomerFactory.java

public class CustomerFactory {

   public static final String[] names = {"Rob", "Joe", "Julie"};

   public static AbstractCustomer getCustomer(String name){

      for (int i = 0; i < names.length; i++) {
         if (names[i].equalsIgnoreCase(name)){
            return new RealCustomer(name);
         }
      }
      return new NullCustomer();
   }
}

ステップ4

_CustomerFactory_を使用して、渡された顧客の名前に基づいて_RealCustomer_または_NullCustomer_オブジェクトを取得します。

NullPatternDemo.java

public class NullPatternDemo {
   public static void main(String[] args) {

      AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");
      AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");
      AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");
      AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");

      System.out.println("Customers");
      System.out.println(customer1.getName());
      System.out.println(customer2.getName());
      System.out.println(customer3.getName());
      System.out.println(customer4.getName());
   }
}

ステップ5

出力を確認します。

Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database

デザインパターン - 戦略パターン

Strategyパターンでは、クラスの動作またはそのアルゴリズムを実行時に変更できます。 このタイプの設計パターンは、動作パターンの下にあります。

戦略パターンでは、さまざまな戦略を表すオブジェクトと、その戦略オブジェクトごとに動作が異なるコンテキストオブジェクトを作成します。 戦略オブジェクトは、コンテキストオブジェクトの実行アルゴリズムを変更します。

実装

アクションを定義する_Strategy_インターフェイスと、_Strategy_インターフェイスを実装する具体的な戦略クラスを作成します。 _Context_は、戦略を使用するクラスです。

デモクラスである_StrategyPatternDemo_は、_Context_および戦略オブジェクトを使用して、展開または使用する戦略に基づくコンテキストの動作の変化を示します。

ストラテジーパターンUML図

ステップ1

インターフェイスを作成します。

Strategy.java

public interface Strategy {
   public int doOperation(int num1, int num2);
}

ステップ2

同じインターフェースを実装する具体的なクラスを作成します。

OperationAdd.java

public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

OperationSubstract.java

public class OperationSubstract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

OperationMultiply.java

public class OperationMultiply implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 *num2;
   }
}

ステップ3

_Context_クラスを作成します。

Context.java

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

ステップ4

_Context_を使用して、_Strategy_を変更したときの動作の変化を確認します。

StrategyPatternDemo.java

public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationSubstract());
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationMultiply());
      System.out.println("10* 5 = " + context.executeStrategy(10, 5));
   }
}

ステップ5

出力を確認します。

10 + 5 = 15
10 - 5 = 5
10 * 5 = 50

デザインパターン-テンプレートパターン

テンプレートパターンでは、抽象クラスはそのメソッドを実行するための定義済みのウェイ/テンプレートを公開します。 そのサブクラスは必要に応じてメソッドの実装をオーバーライドできますが、呼び出しは抽象クラスで定義されたのと同じ方法でなければなりません。 このパターンは、動作パターンカテゴリに分類されます。

実装

オーバーライドできないようにfinalに設定されたテンプレートメソッドで操作を定義する_Game_抽象クラスを作成します。 _Cricket_と_Football_は、_Game_を拡張し、そのメソッドをオーバーライドする具象クラスです。

デモクラス_TemplatePatternDemo_は、_Game_を使用してテンプレートパターンの使用方法を示します。

テンプレートパターンUML図

ステップ1

finalであるテンプレートメソッドで抽象クラスを作成します。

Game.java

public abstract class Game {
   abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();

  //template method
   public final void play(){

     //initialize the game
      initialize();

     //start game
      startPlay();

     //end game
      endPlay();
   }
}

ステップ2

上記のクラスを拡張する具象クラスを作成します。

Cricket.java

public class Cricket extends Game {

   @Override
   void endPlay() {
      System.out.println("Cricket Game Finished!");
   }

   @Override
   void initialize() {
      System.out.println("Cricket Game Initialized! Start playing.");
   }

   @Override
   void startPlay() {
      System.out.println("Cricket Game Started. Enjoy the game!");
   }
}

Football.java

public class Football extends Game {

   @Override
   void endPlay() {
      System.out.println("Football Game Finished!");
   }

   @Override
   void initialize() {
      System.out.println("Football Game Initialized! Start playing.");
   }

   @Override
   void startPlay() {
      System.out.println("Football Game Started. Enjoy the game!");
   }
}

ステップ3

_Game_のテンプレートメソッドplay()を使用して、定義されたゲームのプレイ方法を示します。

TemplatePatternDemo.java

public class TemplatePatternDemo {
   public static void main(String[] args) {

      Game game = new Cricket();
      game.play();
      System.out.println();
      game = new Football();
      game.play();
   }
}

ステップ4

出力を確認します。

Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!

デザインパターン-訪問者パターン

Visitorパターンでは、要素クラスの実行アルゴリズムを変更するvisitorクラスを使用します。 この方法により、要素の実行アルゴリズムは、訪問者が変わると変わる可能性があります。 このパターンは、動作パターンカテゴリに分類されます。 パターンに従って、ビジターオブジェクトが要素オブジェクトの操作を処理するように、要素オブジェクトはビジターオブジェクトを受け入れる必要があります。

実装

accept opearationを定義する_ComputerPart_インターフェースを作成します。 ビジタークラスの操作を定義する別のインターフェイス_ComputerPartVisitor_を定義します。 _Computer_は、具体的なビジターを使用して、対応するアクションを実行します。

デモクラス_VisitorPatternDemo_は、_Computer_クラスと_ComputerPartVisitor_クラスを使用して、訪問者パターンの使用方法を示します。

ビジターパターンUML図

ステップ1

要素を表すインターフェースを定義します。

ComputerPart.java

public interface ComputerPart {
   public void accept(ComputerPartVisitor computerPartVisitor);
}

ステップ2

上記のクラスを拡張する具象クラスを作成します。

Keyboard.java

public class Keyboard implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Monitor.java

public class Monitor implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Mouse.java

public class Mouse implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

Computer.java

public class Computer implements ComputerPart {

   ComputerPart[] parts;

   public Computer(){
      parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
   }


   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      for (int i = 0; i < parts.length; i++) {
         parts[i].accept(computerPartVisitor);
      }
      computerPartVisitor.visit(this);
   }
}

ステップ3

訪問者を表すインターフェースを定義します。

ComputerPartVisitor.java

public interface ComputerPartVisitor {
    public void visit(Computer computer);
    public void visit(Mouse mouse);
    public void visit(Keyboard keyboard);
    public void visit(Monitor monitor);
}

ステップ4

上記のクラスを実装する具体的な訪問者を作成します。

ComputerPartDisplayVisitor.java

public class ComputerPartDisplayVisitor implements ComputerPartVisitor {

   @Override
   public void visit(Computer computer) {
      System.out.println("Displaying Computer.");
   }

   @Override
   public void visit(Mouse mouse) {
      System.out.println("Displaying Mouse.");
   }

   @Override
   public void visit(Keyboard keyboard) {
      System.out.println("Displaying Keyboard.");
   }

   @Override
   public void visit(Monitor monitor) {
      System.out.println("Displaying Monitor.");
   }
}

ステップ5

_ComputerPartDisplayVisitor_を使用して、_Computer_の一部を表示します。

VisitorPatternDemo.java

public class VisitorPatternDemo {
   public static void main(String[] args) {

      ComputerPart computer = new Computer();
      computer.accept(new ComputerPartDisplayVisitor());
   }
}

ステップ6

出力を確認します。

Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.

デザインパターン-MVCパターン

MVCパターンは、Model-View-Controller Patternの略です。 このパターンは、アプリケーションの懸念を分離するために使用されます。

  • モデル-モデルは、データを運ぶオブジェクトまたはJAVA POJOを表します。 また、データが変更された場合にコントローラーを更新するロジックを持つこともできます。
  • 表示-表示は、モデルに含まれるデータの視覚化を表します。
  • コントローラー-コントローラーはモデルとビューの両方で機能します。 モデルオブジェクトへのデータフローを制御し、データが変更されるたびにビューを更新します。 ビューとモデルを分離します。

実装

モデルとして機能する_Student_オブジェクトを作成します。_StudentView_はコンソールに生徒の詳細を印刷できるビュークラスになり、_StudentController_は_Student_オブジェクトにデータを保存し、それに応じてビュー_StudentView_を更新するコントローラークラスです。

デモクラス_MVCPatternDemo_は、_StudentController_を使用して、MVCパターンの使用方法を示します。

MVCパターンUML図

ステップ1

モデルを作成します。

Student.java

public class Student {
   private String rollNo;
   private String name;

   public String getRollNo() {
      return rollNo;
   }

   public void setRollNo(String rollNo) {
      this.rollNo = rollNo;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

ステップ2

ビューを作成します。

StudentView.java

public class StudentView {
   public void printStudentDetails(String studentName, String studentRollNo){
      System.out.println("Student: ");
      System.out.println("Name: " + studentName);
      System.out.println("Roll No: " + studentRollNo);
   }
}

ステップ3

コントローラーを作成します。

StudentController.java

public class StudentController {
   private Student model;
   private StudentView view;

   public StudentController(Student model, StudentView view){
      this.model = model;
      this.view = view;
   }

   public void setStudentName(String name){
      model.setName(name);
   }

   public String getStudentName(){
      return model.getName();
   }

   public void setStudentRollNo(String rollNo){
      model.setRollNo(rollNo);
   }

   public String getStudentRollNo(){
      return model.getRollNo();
   }

   public void updateView(){
      view.printStudentDetails(model.getName(), model.getRollNo());
   }
}

ステップ4

_StudentController_メソッドを使用して、MVCデザインパターンの使用方法を示します。

MVCPatternDemo.java

public class MVCPatternDemo {
   public static void main(String[] args) {

     //fetch student record based on his roll no from the database
      Student model  = retriveStudentFromDatabase();

     //Create a view : to write student details on console
      StudentView view = new StudentView();

      StudentController controller = new StudentController(model, view);

      controller.updateView();

     //update model data
      controller.setStudentName("John");

      controller.updateView();
   }

   private static Student retriveStudentFromDatabase(){
      Student student = new Student();
      student.setName("Robert");
      student.setRollNo("10");
      return student;
   }
}

ステップ5

出力を確認します。

Student:
Name: Robert
Roll No: 10
Student:
Name: John
Roll No: 10

デザインパターン-ビジネスデリゲートパターン

Business Delegate Patternは、プレゼンテーション層とビジネス層を分離するために使用されます。 基本的には、プレゼンテーション層コード内のビジネス層コードへの通信またはリモートルックアップ機能を減らすために使用されます。 ビジネス層には、次のエンティティがあります。

  • クライアント-プレゼンテーション層のコードは、JSP、サーブレット、またはUI Javaコードです。
  • ビジネスデリゲート-ビジネスエンティティメソッドへのアクセスを提供するクライアントエンティティの単一エントリポイントクラス。
  • ルックアップサービス-ルックアップサービスオブジェクトは、相対的なビジネス実装を取得し、ビジネスデリゲートオブジェクトへのビジネスオブジェクトアクセスを提供します。
  • ビジネスサービス-ビジネスサービスインターフェイス。 具体的なクラスは、このビジネスサービスを実装して、実際のビジネス実装ロジックを提供します。

実装

Business Delegateパターンのさまざまなエンティティを表す_Client BusinessDelegate BusinessService LookUpService JMSService_、および_EJBService_を作成します。

デモクラスである_BusinessDelegatePatternDemo_は、_BusinessDelegate_および_Client_を使用して、Business Delegateパターンの使用方法を示します。

ビジネスデリゲートパターンUMLダイアグラム

ステップ1

BusinessServiceインターフェイスを作成します。

BusinessService.java

public interface BusinessService {
   public void doProcessing();
}

ステップ2

具体的なサービスクラスを作成します。

EJBService.java

public class EJBService implements BusinessService {

   @Override
   public void doProcessing() {
      System.out.println("Processing task by invoking EJB Service");
   }
}

JMSService.java

public class JMSService implements BusinessService {

   @Override
   public void doProcessing() {
      System.out.println("Processing task by invoking JMS Service");
   }
}

ステップ3

ビジネス検索サービスを作成します。

BusinessLookUp.java

public class BusinessLookUp {
   public BusinessService getBusinessService(String serviceType){

      if(serviceType.equalsIgnoreCase("EJB")){
         return new EJBService();
      }
      else {
         return new JMSService();
      }
   }
}

ステップ4

ビジネスデリゲートを作成します。

BusinessDelegate.java

public class BusinessDelegate {
   private BusinessLookUp lookupService = new BusinessLookUp();
   private BusinessService businessService;
   private String serviceType;

   public void setServiceType(String serviceType){
      this.serviceType = serviceType;
   }

   public void doTask(){
      businessService = lookupService.getBusinessService(serviceType);
      businessService.doProcessing();
   }
}

ステップ5

クライアントを作成します。

Client.java

public class Client {

   BusinessDelegate businessService;

   public Client(BusinessDelegate businessService){
      this.businessService  = businessService;
   }

   public void doTask(){
      businessService.doTask();
   }
}

ステップ6

BusinessDelegateおよびClientクラスを使用して、Business Delegateパターンを示します。

BusinessDelegatePatternDemo.java

public class BusinessDelegatePatternDemo {

   public static void main(String[] args) {

      BusinessDelegate businessDelegate = new BusinessDelegate();
      businessDelegate.setServiceType("EJB");

      Client client = new Client(businessDelegate);
      client.doTask();

      businessDelegate.setServiceType("JMS");
      client.doTask();
   }
}

ステップ7

出力を確認します。

Processing task by invoking EJB Service
Processing task by invoking JMS Service

デザインパターン-複合エンティティパターン

複合エンティティパターンは、EJB永続化メカニズムで使用されます。 複合エンティティは、オブジェクトのグラフを表すEJBエンティティBeanです。 複合エンティティが更新されると、内部的に依存するオブジェクトBeanは、EJBエンティティBeanによって管理されていると自動的に更新されます。 以下は、複合エンティティBeanの参加者です。

  • 複合エンティティ-プライマリエンティティBeanです。 粗くすることも、永続化のために使用する粗いオブジェクトを含めることもできます。
  • 粗視化オブジェクト-このオブジェクトには依存オブジェクトが含まれます。 独自のライフサイクルがあり、依存オブジェクトのライフサイクルも管理します。
  • 依存オブジェクト-依存オブジェクトとは、その永続性のライフサイクルを粗視化オブジェクトに依存するオブジェクトです。
  • 戦略-戦略は、複合エンティティの実装方法を表します。

実装

CompositeEntityとして機能する_CompositeEntity_オブジェクトを作成します。 CoarseGrainedObject_は、依存オブジェクトを含むクラスになります。 _CompositeEntityPatternDemo、デモクラスは_Client_クラスを使用して、複合エンティティパターンの使用方法を示します。

複合エンティティパターンUML図

ステップ1

依存オブジェクトを作成します。

DependentObject1.java

public class DependentObject1 {

   private String data;

   public void setData(String data){
      this.data = data;
   }

   public String getData(){
      return data;
   }
}

DependentObject2.java

public class DependentObject2 {

   private String data;

   public void setData(String data){
      this.data = data;
   }

   public String getData(){
      return data;
   }
}

ステップ2

粗視化オブジェクトを作成します。

CoarseGrainedObject.java

public class CoarseGrainedObject {
   DependentObject1 do1 = new DependentObject1();
   DependentObject2 do2 = new DependentObject2();

   public void setData(String data1, String data2){
      do1.setData(data1);
      do2.setData(data2);
   }

   public String[] getData(){
      return new String[] {do1.getData(),do2.getData()};
   }
}

ステップ3

複合エンティティを作成します。

CompositeEntity.java

public class CompositeEntity {
   private CoarseGrainedObject cgo = new CoarseGrainedObject();

   public void setData(String data1, String data2){
      cgo.setData(data1, data2);
   }

   public String[] getData(){
      return cgo.getData();
   }
}

ステップ4

複合エンティティを使用するクライアントクラスを作成します。

Client.java

public class Client {
   private CompositeEntity compositeEntity = new CompositeEntity();

   public void printData(){

      for (int i = 0; i < compositeEntity.getData().length; i++) {
         System.out.println("Data: " + compositeEntity.getData()[i]);
      }
   }

   public void setData(String data1, String data2){
      compositeEntity.setData(data1, data2);
   }
}

ステップ5

_Client_を使用して、複合エンティティデザインパターンの使用方法を示します。

CompositeEntityPatternDemo.java

public class CompositeEntityPatternDemo {
   public static void main(String[] args) {

       Client client = new Client();
       client.setData("Test", "Data");
       client.printData();
       client.setData("Second Test", "Data1");
       client.printData();
   }
}

ステップ6

出力を確認します。

Data: Test
Data: Data
Data: Second Test
Data: Data1

データアクセスオブジェクトパターン

データアクセスオブジェクトパターンまたはDAOパターンは、低レベルのデータアクセスAPIまたは操作を高レベルのビジネスサービスから分離するために使用されます。 以下は、データアクセスオブジェクトパターンの参加者です。

  • データアクセスオブジェクトインターフェイス-このインターフェイスは、モデルオブジェクトで実行される標準操作を定義します。
  • データアクセスオブジェクトコンクリートクラス-このクラスは上記のインターフェイスを実装します。 このクラスは、データベース/xmlまたはその他のストレージメカニズムであるデータソースからデータを取得します。
  • モデルオブジェクトまたは値オブジェクト-このオブジェクトは、DAOクラスを使用して取得したデータを格納するget/setメソッドを含む単純なPOJOです。

実装

モデルまたは値オブジェクトとして機能する_Student_オブジェクトを作成します。_StudentDao_はデータアクセスオブジェクトインターフェイスです。_StudentDaoImpl_はデータアクセスオブジェクトインターフェイスを実装する具体的なクラスです。 デモクラス_DaoPatternDemo_は、_StudentDao_を使用して、データアクセスオブジェクトパターンの使用方法を示します。

データアクセスオブジェクトパターンUML図

ステップ1

値オブジェクトを作成します。

Student.java

public class Student {
   private String name;
   private int rollNo;

   Student(String name, int rollNo){
      this.name = name;
      this.rollNo = rollNo;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getRollNo() {
      return rollNo;
   }

   public void setRollNo(int rollNo) {
      this.rollNo = rollNo;
   }
}

ステップ2

データアクセスオブジェクトインターフェイスを作成します。

StudentDao.java

import java.util.List;

public interface StudentDao {
   public List<Student> getAllStudents();
   public Student getStudent(int rollNo);
   public void updateStudent(Student student);
   public void deleteStudent(Student student);
}

ステップ3

上記のインターフェイスを実装する具体的なクラスを作成します。

StudentDaoImpl.java

import java.util.ArrayList;
import java.util.List;

public class StudentDaoImpl implements StudentDao {

  //list is working as a database
   List<Student> students;

   public StudentDaoImpl(){
      students = new ArrayList<Student>();
      Student student1 = new Student("Robert",0);
      Student student2 = new Student("John",1);
      students.add(student1);
      students.add(student2);
   }
   @Override
   public void deleteStudent(Student student) {
      students.remove(student.getRollNo());
      System.out.println("Student: Roll No " + student.getRollNo() + ", deleted from database");
   }

  //retrive list of students from the database
   @Override
   public List<Student> getAllStudents() {
      return students;
   }

   @Override
   public Student getStudent(int rollNo) {
      return students.get(rollNo);
   }

   @Override
   public void updateStudent(Student student) {
      students.get(student.getRollNo()).setName(student.getName());
      System.out.println("Student: Roll No " + student.getRollNo() + ", updated in the database");
   }
}

ステップ4

_StudentDao_を使用して、データアクセスオブジェクトパターンの使用方法を示します。

DaoPatternDemo.java

public class DaoPatternDemo {
   public static void main(String[] args) {
      StudentDao studentDao = new StudentDaoImpl();

     //print all students
      for (Student student : studentDao.getAllStudents()) {
         System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]");
      }


     //update student
      Student student =studentDao.getAllStudents().get(0);
      student.setName("Michael");
      studentDao.updateStudent(student);

     //get the student
      studentDao.getStudent(0);
      System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]");
   }
}

ステップ5

出力を確認します。

Student: [RollNo : 0, Name : Robert ]
Student: [RollNo : 1, Name : John ]
Student: Roll No 0, updated in the database
Student: [RollNo : 0, Name : Michael ]

デザインパターン-フロントコントローラーパターン

フロントコントローラーの設計パターンは、すべてのリクエストが単一のハンドラーによって処理されるように、集中化されたリクエスト処理メカニズムを提供するために使用されます。 このハンドラーは、要求の認証/承認/ログ記録または追跡を行い、対応するハンドラーに要求を渡すことができます。 以下は、このタイプのデザインパターンのエンティティです。

  • フロントコントローラー-アプリケーション(Webベース/デスクトップベース)に送信されるすべての種類の要求に対する単一のハンドラー。
  • Dispatcher -フロントコントローラーは、対応する特定のハンドラーに要求をディスパッチできるディスパッチャーオブジェクトを使用できます。
  • View -ビューは、リクエストが行われるオブジェクトです。

実装

_FrontController_と_Dispatcher_を作成して、フロントコントローラーとDispatcherとして対応するように機能させます。 _HomeView_および_StudentView_は、リクエストがフロントコントローラーに届くさまざまなビューを表します。

デモクラス_FrontControllerPatternDemo_は、_FrontController_を使用して、フロントコントローラーの設計パターンを示します。

フロントコントローラーパターンUML図

ステップ1

ビューを作成します。

HomeView.java

public class HomeView {
   public void show(){
      System.out.println("Displaying Home Page");
   }
}

StudentView.java

public class StudentView {
   public void show(){
      System.out.println("Displaying Student Page");
   }
}

ステップ2

ディスパッチャを作成します。

Dispatcher.java

public class Dispatcher {
   private StudentView studentView;
   private HomeView homeView;

   public Dispatcher(){
      studentView = new StudentView();
      homeView = new HomeView();
   }

   public void dispatch(String request){
      if(request.equalsIgnoreCase("STUDENT")){
         studentView.show();
      }
      else{
         homeView.show();
      }
   }
}

ステップ3

FrontControllerを作成する

FrontController.java

public class FrontController {

   private Dispatcher dispatcher;

   public FrontController(){
      dispatcher = new Dispatcher();
   }

   private boolean isAuthenticUser(){
      System.out.println("User is authenticated successfully.");
      return true;
   }

   private void trackRequest(String request){
      System.out.println("Page requested: " + request);
   }

   public void dispatchRequest(String request){
     //log each request
      trackRequest(request);

     //authenticate the user
      if(isAuthenticUser()){
         dispatcher.dispatch(request);
      }
   }
}

ステップ4

_FrontController_を使用して、フロントコントローラーの設計パターンを示します。

FrontControllerPatternDemo.java

public class FrontControllerPatternDemo {
   public static void main(String[] args) {

      FrontController frontController = new FrontController();
      frontController.dispatchRequest("HOME");
      frontController.dispatchRequest("STUDENT");
   }
}

ステップ5

出力を確認します。

Page requested: HOME
User is authenticated successfully.
Displaying Home Page
Page requested: STUDENT
User is authenticated successfully.
Displaying Student Page

デザインパターン-インターセプトフィルターパターン

インターセプトフィルターの設計パターンは、アプリケーションの要求または応答を使用して前処理/後処理を行う場合に使用されます。 要求を実際のターゲットアプリケーションに渡す前に、フィルターが要求に定義されて適用されます。 フィルターは、要求の認証/許可/ログ記録または追跡を実行し、対応するハンドラーに要求を渡すことができます。 以下は、このタイプのデザインパターンのエンティティです。

  • フィルター-要求ハンドラーによる要求の実行の前または後に特定のタスクを実行するフィルター。
  • フィルターチェーン-フィルターチェーンには複数のフィルターが搭載されており、ターゲットで定義された順序でフィルターを実行できます。
  • ターゲット-ターゲットオブジェクトはリクエストハンドラーです
  • フィルターマネージャー-フィルターマネージャーは、フィルターとフィルターチェーンを管理します。
  • クライアント-クライアントは、ターゲットオブジェクトにリクエストを送信するオブジェクトです。

実装

エンティティを表すさまざまなオブジェクトとして、FilterChain _、 FilterManager Target Client_を作成します。_AuthenticationFilter_と_DebugFilter_は、具体的なフィルターを表します。

デモクラス_InterceptingFilterDemo_は、_Client_を使用して、インターセプティングフィルターの設計パターンを示します。

Intercepting Filter Pattern UML Diagram

ステップ1

フィルターインターフェイスを作成します。

Filter.java

public interface Filter {
   public void execute(String request);
}

ステップ2

具体的なフィルターを作成します。

AuthenticationFilter.java

public class AuthenticationFilter implements Filter {
   public void execute(String request){
      System.out.println("Authenticating request: " + request);
   }
}

DebugFilter.java

public class DebugFilter implements Filter {
   public void execute(String request){
      System.out.println("request log: " + request);
   }
}

ステップ3

ターゲットを作成

Target.java

public class Target {
   public void execute(String request){
      System.out.println("Executing request: " + request);
   }
}

ステップ4

フィルターチェーンの作成

FilterChain.java

import java.util.ArrayList;
import java.util.List;

public class FilterChain {
   private List<Filter> filters = new ArrayList<Filter>();
   private Target target;

   public void addFilter(Filter filter){
      filters.add(filter);
   }

   public void execute(String request){
      for (Filter filter : filters) {
         filter.execute(request);
      }
      target.execute(request);
   }

   public void setTarget(Target target){
      this.target = target;
   }
}

ステップ5

フィルターマネージャーの作成

FilterManager.java

public class FilterManager {
   FilterChain filterChain;

   public FilterManager(Target target){
      filterChain = new FilterChain();
      filterChain.setTarget(target);
   }
   public void setFilter(Filter filter){
      filterChain.addFilter(filter);
   }

   public void filterRequest(String request){
      filterChain.execute(request);
   }
}

ステップ6

クライアントを作成

Client.java

public class Client {
   FilterManager filterManager;

   public void setFilterManager(FilterManager filterManager){
      this.filterManager = filterManager;
   }

   public void sendRequest(String request){
      filterManager.filterRequest(request);
   }
}

ステップ7

_Client_を使用して、インターセプトフィルターの設計パターンを示します。

InterceptingFilterDemo.java

public class InterceptingFilterDemo {
   public static void main(String[] args) {
      FilterManager filterManager = new FilterManager(new Target());
      filterManager.setFilter(new AuthenticationFilter());
      filterManager.setFilter(new DebugFilter());

      Client client = new Client();
      client.setFilterManager(filterManager);
      client.sendRequest("HOME");
   }
}

ステップ8

出力を確認します。

Authenticating request: HOME
request log: HOME
Executing request: HOME

デザインパターン-サービスロケーターパターン

サービスロケーターデザインパターンは、JNDIルックアップを使用してさまざまなサービスを検索するときに使用されます。 サービスのJNDIを検索するコストが高いことを考慮して、Service Locatorパターンはキャッシング手法を使用します。 サービスが初めて必要になると、Service LocatorはJNDIで検索し、サービスオブジェクトをキャッシュします。 さらに検索またはService Locatorを介した同じサービスがキャッシュで実行されるため、アプリケーションのパフォーマンスが大幅に向上します。 以下は、このタイプのデザインパターンのエンティティです。

  • サービス-リクエストを処理する実際のサービス。 このようなサービスの参照は、JNDIサーバーで確認する必要があります。
  • コンテキスト/初期コンテキスト-JNDIコンテキストは、ルックアップの目的で使用されるサービスへの参照を保持します。
  • Service Locator -Service Locatorは、サービスをキャッシュするJNDIルックアップによってサービスを取得するための単一の連絡先です。
  • キャッシュ-サービスの参照を保存して再利用するためのキャッシュ
  • クライアント-クライアントは、ServiceLocatorを介してサービスを呼び出すオブジェクトです。

実装

エンティティを表すさまざまなオブジェクトとして_ServiceLocator InitialContext_、Cache、_Service_を作成します。_Service1_と_Service2_は具体的なサービスを表します。

デモクラス_ServiceLocatorPatternDemo_は、ここでクライアントとして機能し、_ServiceLocator_を使用してService Locatorのデザインパターンを示します。

サービスロケーターパターンUML図

ステップ1

サービスインターフェイスを作成します。

Service.java

public interface Service {
   public String getName();
   public void execute();
}

ステップ2

具体的なサービスを作成します。

Service1.java

public class Service1 implements Service {
   public void execute(){
      System.out.println("Executing Service1");
   }

   @Override
   public String getName() {
      return "Service1";
   }
}

Service2.java

public class Service2 implements Service {
   public void execute(){
      System.out.println("Executing Service2");
   }

   @Override
   public String getName() {
      return "Service2";
   }
}

ステップ3

JNDIルックアップ用のInitialContextを作成します

InitialContext.java

public class InitialContext {
   public Object lookup(String jndiName){

      if(jndiName.equalsIgnoreCase("SERVICE1")){
         System.out.println("Looking up and creating a new Service1 object");
         return new Service1();
      }
      else if (jndiName.equalsIgnoreCase("SERVICE2")){
         System.out.println("Looking up and creating a new Service2 object");
         return new Service2();
      }
      return null;
   }
}

ステップ4

キャッシュを作成

Cache.java

import java.util.ArrayList;
import java.util.List;

public class Cache {

   private List<Service> services;

   public Cache(){
      services = new ArrayList<Service>();
   }

   public Service getService(String serviceName){

      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(serviceName)){
            System.out.println("Returning cached  " + serviceName + " object");
            return service;
         }
      }
      return null;
   }

   public void addService(Service newService){
      boolean exists = false;

      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(newService.getName())){
            exists = true;
         }
      }
      if(!exists){
         services.add(newService);
      }
   }
}

ステップ5

サービスロケーターの作成

ServiceLocator.java

public class ServiceLocator {
   private static Cache cache;

   static {
      cache = new Cache();
   }

   public static Service getService(String jndiName){

      Service service = cache.getService(jndiName);

      if(service != null){
         return service;
      }

      InitialContext context = new InitialContext();
      Service service1 = (Service)context.lookup(jndiName);
      cache.addService(service1);
      return service1;
   }
}

ステップ6

_ServiceLocator_を使用して、Service Locator Design Patternを示します。

ServiceLocatorPatternDemo.java

public class ServiceLocatorPatternDemo {
   public static void main(String[] args) {
      Service service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();
      service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();
   }
}

ステップ7

出力を確認します。

Looking up and creating a new Service1 object
Executing Service1
Looking up and creating a new Service2 object
Executing Service2
Returning cached  Service1 object
Executing Service1
Returning cached  Service2 object
Executing Service2

デザインパターン-オブジェクトパターンの転送

Transfer Objectパターンは、クライアントからサーバーへのワンショットで複数の属性を持つデータを渡したいときに使用されます。 転送オブジェクトは値オブジェクトとも呼ばれます。 転送オブジェクトは、getter/setterメソッドを備えた単純なPOJOクラスであり、ネットワーク経由で転送できるようにシリアル化できます。 動作はありません。 サーバー側のビジネスクラスは、通常、データベースからデータをフェッチし、POJOに入力してクライアントに送信するか、値で渡します。 クライアントの場合、転送オブジェクトは読み取り専用です。 クライアントは、独自の転送オブジェクトを作成してサーバーに渡し、データベース内の値を一度に更新できます。 以下は、このタイプのデザインパターンのエンティティです。

  • ビジネスオブジェクト-ビジネスサービスは、転送オブジェクトにデータを入力します。
  • Transfer Object -属性のみを設定/取得するメソッドを持つ単純なPOJO。
  • クライアント-クライアントは、転送オブジェクトをビジネスオブジェクトに要求または送信します。

実装

エンティティを表す_StudentBO_をビジネスオブジェクトとして、_Student_を転送オブジェクトとして作成します。

デモクラス_TransferObjectPatternDemo_は、ここでクライアントとして機能し、_StudentBO_および_Student_を使用して、Transfer Object Design Patternを示します。

Transfer Object Pattern UML Diagram

ステップ1

転送オブジェクトを作成します。

StudentVO.java

public class StudentVO {
   private String name;
   private int rollNo;

   StudentVO(String name, int rollNo){
      this.name = name;
      this.rollNo = rollNo;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getRollNo() {
      return rollNo;
   }

   public void setRollNo(int rollNo) {
      this.rollNo = rollNo;
   }
}

ステップ2

ビジネスオブジェクトを作成します。

StudentBO.java

import java.util.ArrayList;
import java.util.List;

public class StudentBO {

  //list is working as a database
   List<StudentVO> students;

   public StudentBO(){
      students = new ArrayList<StudentVO>();
      StudentVO student1 = new StudentVO("Robert",0);
      StudentVO student2 = new StudentVO("John",1);
      students.add(student1);
      students.add(student2);
   }
   public void deleteStudent(StudentVO student) {
      students.remove(student.getRollNo());
      System.out.println("Student: Roll No " + student.getRollNo() + ", deleted from database");
   }

  //retrive list of students from the database
   public List<StudentVO> getAllStudents() {
      return students;
   }

   public StudentVO getStudent(int rollNo) {
      return students.get(rollNo);
   }

   public void updateStudent(StudentVO student) {
      students.get(student.getRollNo()).setName(student.getName());
      System.out.println("Student: Roll No " + student.getRollNo() +", updated in the database");
   }
}

ステップ3

_StudentBO_を使用して、Transfer Object Design Patternを示します。

TransferObjectPatternDemo.java

public class TransferObjectPatternDemo {
   public static void main(String[] args) {
      StudentBO studentBusinessObject = new StudentBO();

     //print all students
      for (StudentVO student : studentBusinessObject.getAllStudents()) {
         System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]");
      }

     //update student
      StudentVO student = studentBusinessObject.getAllStudents().get(0);
      student.setName("Michael");
      studentBusinessObject.updateStudent(student);

     //get the student
      student = studentBusinessObject.getStudent(0);
      System.out.println("Student: [RollNo : " + student.getRollNo() + ", Name : " + student.getName() + " ]");
   }
}

ステップ4

出力を確認します。

Student: [RollNo : 0, Name : Robert ]
Student: [RollNo : 1, Name : John ]
Student: Roll No 0, updated in the database
Student: [RollNo : 0, Name : Michael ]

Design-pattern-questions-answers

デザインパターン-便利なリソース

次のリソースには、デザインパターンに関する追加情報が含まれています。 これについての詳細な知識を得るためにそれらを使用してください。

デザインパターンに関する便利なリンク

Javaデザインパターンに関する有用な書籍

このページにサイトを登録するには、 contact @ finddevguides.com にメールを送信してください。