これは、デザイン パターンに関する一連のブログの始まりです。このブログでは、最初のタイプのデザイン パターンであるクリエーション パターンについて説明します。ここでは、創作パターンに該当するタイプについて、いくつかの実例を交えて説明します。選択言語として Java を使用します。
デザイン パターンはソフトウェア開発において重要な役割を果たし、一般的な問題に対する実証済みのソリューションを提供し、ベスト プラクティスを促進します。これらは、コード内で繰り返し発生する設計上の問題を解決するためにカスタマイズできる、あらかじめ作成された青写真のようなものです。
オブジェクト指向プログラミングでは、作成デザイン パターンが重要な役割を果たします。これにより、オブジェクトのインスタンス化をその使用から分離できるため、オブジェクト作成の柔軟性とスケーラビリティが向上します。このブログ投稿では、ファクトリ メソッド、アブストラクト ファクトリ、ビルダー、プロトタイプ、シングルトンという 5 つの主要なタイプの創作デザイン パターンに焦点を当てます。それぞれがどのように機能するかを示すために、Java での実世界の例を使用します。
1.ファクトリーメソッド
Factory Method パターンはオブジェクトを作成するためのインターフェイスを定義しますが、サブクラスは作成されるオブジェクトのタイプを変更できます。このパターンは Java での疎結合をサポートし、アプリケーション固有のクラスをコードにバインドする必要をなくします。
現実のシナリオ: トラックや船などのさまざまな車両を使用して商品を輸送する物流会社を考えてみましょう。車両のタイプは、必要な輸送モードによって異なります。
// Product Interface interface Transport { void deliver(); } // Concrete Products class Truck implements Transport { @Override public void deliver() { System.out.println("Deliver by land in a truck."); } } class Ship implements Transport { @Override public void deliver() { System.out.println("Deliver by sea in a ship."); } } // Creator abstract class Logistics { public abstract Transport createTransport(); public void planDelivery() { Transport transport = createTransport(); transport.deliver(); } } // Concrete Creators class RoadLogistics extends Logistics { @Override public Transport createTransport() { return new Truck(); } } class SeaLogistics extends Logistics { @Override public Transport createTransport() { return new Ship(); } } // let's call the main class public class Main { public static void main(String[] args) { Logistics logistics = new RoadLogistics(); logistics.planDelivery(); logistics = new SeaLogistics(); logistics.planDelivery(); } }
2.アブストラクトファクトリー
Abstract Factory パターンは、具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリーを作成するためのインターフェイスを提供します。これは、システムがオブジェクトの作成方法から独立している必要がある場合に便利です。
現実のシナリオ: ビクトリア朝やモダンなど、さまざまな種類の家具セットを販売している家具店を想像してください。各セットには椅子やソファなどの商品が含まれます。
// Abstract Products interface Chair { void sitOn(); } interface Sofa { void lieOn(); } // Concrete Products class VictorianChair implements Chair { @Override public void sitOn() { System.out.println("Sitting on a Victorian chair."); } } class ModernChair implements Chair { @Override public void sitOn() { System.out.println("Sitting on a Modern chair."); } } class VictorianSofa implements Sofa { @Override public void lieOn() { System.out.println("Lying on a Victorian sofa."); } } class ModernSofa implements Sofa { @Override public void lieOn() { System.out.println("Lying on a Modern sofa."); } } // Abstract Factory interface FurnitureFactory { Chair createChair(); Sofa createSofa(); } // Concrete Factories class VictorianFurnitureFactory implements FurnitureFactory { @Override public Chair createChair() { return new VictorianChair(); } @Override public Sofa createSofa() { return new VictorianSofa(); } } class ModernFurnitureFactory implements FurnitureFactory { @Override public Chair createChair() { return new ModernChair(); } @Override public Sofa createSofa() { return new ModernSofa(); } } // Client code public class Main { private static void createFurniture(FurnitureFactory factory) { Chair chair = factory.createChair(); Sofa sofa = factory.createSofa(); chair.sitOn(); sofa.lieOn(); } public static void main(String[] args) { FurnitureFactory victorianFactory = new VictorianFurnitureFactory(); createFurniture(victorianFactory); FurnitureFactory modernFactory = new ModernFurnitureFactory(); createFurniture(modernFactory); } }
3.ビルダー
Builder パターンは、複雑なオブジェクトの構築をその表現から分離し、同じ構築プロセスで異なる表現を作成できるようにします。これは、多くのオプション属性を持つオブジェクトを作成する場合に特に便利です。
現実のシナリオ: 顧客がさまざまなトッピング、サイズ、生地の種類でピザをカスタマイズできるオンライン ピザ注文システムを考えてみましょう。
// Product class Pizza { private String dough = ""; private String sauce = ""; private String topping = ""; public void setDough(String dough) { this.dough = dough; } public void setSauce(String sauce) { this.sauce = sauce; } public void setTopping(String topping) { this.topping = topping; } @Override public String toString() { return "Pizza [dough=" dough ", sauce=" sauce ", topping=" topping "]"; } } // Builder Interface interface PizzaBuilder { void buildDough(); void buildSauce(); void buildTopping(); Pizza getPizza(); } // Concrete Builders class HawaiianPizzaBuilder implements PizzaBuilder { private Pizza pizza; public HawaiianPizzaBuilder() { this.pizza = new Pizza(); } @Override public void buildDough() { pizza.setDough("cross"); } @Override public void buildSauce() { pizza.setSauce("mild"); } @Override public void buildTopping() { pizza.setTopping("ham pineapple"); } @Override public Pizza getPizza() { return this.pizza; } } class SpicyPizzaBuilder implements PizzaBuilder { private Pizza pizza; public SpicyPizzaBuilder() { this.pizza = new Pizza(); } @Override public void buildDough() { pizza.setDough("pan baked"); } @Override public void buildSauce() { pizza.setSauce("hot"); } @Override public void buildTopping() { pizza.setTopping("pepperoni salami"); } @Override public Pizza getPizza() { return this.pizza; } } // Director class Waiter { private PizzaBuilder pizzaBuilder; public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; } public Pizza getPizza() { return pizzaBuilder.getPizza(); } public void constructPizza() { pizzaBuilder.buildDough(); pizzaBuilder.buildSauce(); pizzaBuilder.buildTopping(); } } // Client code public class Main { public static void main(String[] args) { Waiter waiter = new Waiter(); PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder(); PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder(); waiter.setPizzaBuilder(hawaiianPizzaBuilder); waiter.constructPizza(); Pizza pizza1 = waiter.getPizza(); System.out.println("Pizza built: " pizza1); waiter.setPizzaBuilder(spicyPizzaBuilder); waiter.constructPizza(); Pizza pizza2 = waiter.getPizza(); System.out.println("Pizza built: " pizza2); } }
4.プロトタイプ
プロトタイプ パターンは、プロトタイプと呼ばれる既存のオブジェクトをコピーすることによって新しいオブジェクトを作成するために使用されます。このパターンは、新しいオブジェクトの作成コストが高い場合に便利です。
現実のシナリオ: 図形を作成、複製、編集できるグラフィカル エディターについて考えてみましょう。
import java.util.HashMap; import java.util.Map; // Prototype 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; } } // Concrete Prototypes class Rectangle extends Shape { public Rectangle() { type = "Rectangle"; } @Override public void draw() { System.out.println("Drawing a Rectangle."); } } class Circle extends Shape { public Circle() { type = "Circle"; } @Override public void draw() { System.out.println("Drawing a Circle."); } } // Prototype Registry class ShapeCache { private static MapshapeMap = new HashMap(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } public static void loadCache() { Rectangle rectangle = new Rectangle(); rectangle.setId("1"); shapeMap.put(rectangle.getId(), rectangle); Circle circle = new Circle(); circle.setId("2"); shapeMap.put(circle.getId(), circle); } } // Client code public class Main { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape1 = ShapeCache.getShape("1"); System.out.println("Shape: " clonedShape1.getType()); Shape clonedShape2 = ShapeCache.getShape("2"); System.out.println("Shape: " clonedShape2.getType()); } }
5.シングルトン
シングルトン パターンでは、クラスのインスタンスが 1 つだけであることが保証され、そのインスタンスへのグローバル アクセス ポイントが提供されます。このパターンは、ログ記録、キャッシュ、スレッド プールによく使用されます。
現実のシナリオ: 1 つのインスタンスだけがすべての印刷ジョブを管理するプリンター スプーラーを想像してください。
class PrinterSpooler { private static PrinterSpooler instance; private PrinterSpooler() { // private constructor to prevent instantiation } public static PrinterSpooler getInstance() { if (instance == null) { instance = new PrinterSpooler(); } return instance; } public void print(String document) { System.out.println("Printing document: " document); } } // Client code public class Main { public static void main(String[] args) { PrinterSpooler spooler1 = PrinterSpooler.getInstance(); PrinterSpooler spooler2 = PrinterSpooler.getInstance(); spooler1.print("Document 1"); spooler2.print("Document 2"); System.out.println("Are both spoolers the same instance? " (spooler1 == spooler2)); } }
https://refactoring.guru/
https://www.javatpoint.com/design-patterns-in-java
https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3