「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > 完璧なコードの作成: 作成パターンを理解する

完璧なコードの作成: 作成パターンを理解する

2024 年 8 月 25 日に公開
ブラウズ:805

Creating the Perfect Code: Understanding Creational Patterns

これは、デザイン パターンに関する一連のブログの始まりです。このブログでは、最初のタイプのデザイン パターンであるクリエーション パターンについて説明します。ここでは、創作パターンに該当するタイプについて、いくつかの実例を交えて説明します。選択言語として Java を使用します。

デザインパターンとは何ですか?

デザイン パターンはソフトウェア開発において重要な役割を果たし、一般的な問題に対する実証済みのソリューションを提供し、ベスト プラクティスを促進します。これらは、コード内で繰り返し発生する設計上の問題を解決するためにカスタマイズできる、あらかじめ作成された青写真のようなものです。

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 Map shapeMap = 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

リリースステートメント この記事は次の場所に転載されています: https://dev.to/tharindufdo/creating-the-perfect-code- Understanding-creational-patterns-1ld6?1 侵害がある場合は、[email protected] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3