"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > إنشاء الكود المثالي: فهم الأنماط الإبداعية

إنشاء الكود المثالي: فهم الأنماط الإبداعية

تم النشر بتاريخ 2024-08-25
تصفح:371

Creating the Perfect Code: Understanding Creational Patterns

هذه بداية لسلسلة من المدونات حول أنماط التصميم. في هذه المدونة سنناقش النوع الأول من أنماط التصميم وهو الأنماط الإبداعية. هنا ستتم مناقشة الأنواع التي تندرج تحت الأنماط الإبداعية مع بعض الأمثلة الواقعية. سأستخدم جافا كلغة اختياري.

ما هي أنماط التصميم؟

تلعب أنماط التصميم دورًا حاسمًا في تطوير البرمجيات، حيث توفر حلولاً مثبتة للمشاكل الشائعة وتعزيز أفضل الممارسات. إنها تشبه المخططات المعدة مسبقًا والتي يمكنك تخصيصها لحل مشكلة التصميم المتكررة في التعليمات البرمجية الخاصة بك.

استكشاف أنماط التصميم الإبداعي في جافا

في البرمجة الموجهة للكائنات، تلعب أنماط التصميم الإبداعي دورًا مهمًا لأنها تجعل من الممكن فصل إنشاء الكائنات عن استخدامها وبالتالي زيادة المرونة وقابلية التوسع في إنشاء الكائنات. ستركز مشاركة المدونة هذه على خمسة أنواع رئيسية من أنماط التصميم الإبداعي: ​​طريقة المصنع، والمصنع المجرد، والباني، والنموذج الأولي، والمفردة. ولإظهار كيفية عمل كل منها، سنستخدم أمثلة واقعية في Java.

1. طريقة المصنع

يحدد نمط أسلوب المصنع واجهة لإنشاء كائن ولكنه يسمح للفئات الفرعية بتغيير نوع الكائنات التي سيتم إنشاؤها. يدعم هذا النمط الاقتران غير المحكم في 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. منشئ

يفصل نمط البناء بناء كائن معقد عن تمثيله، مما يسمح لنفس عملية البناء بإنشاء تمثيلات مختلفة. وهو مفيد بشكل خاص لإنشاء كائنات ذات سمات اختيارية عديدة.

سيناريو الحياة الواقعية: خذ بعين الاعتبار نظام طلب البيتزا عبر الإنترنت حيث يمكن للعملاء تخصيص البيتزا الخاصة بهم بمختلف الإضافات والأحجام وأنواع القشرة.

// 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. سينغلتون

يضمن نمط Singleton أن يحتوي الفصل على مثيل واحد فقط ويوفر نقطة وصول عالمية إليه. يُستخدم هذا النمط بشكل شائع للتسجيل والتخزين المؤقت وتجمعات الخيوط.

سيناريو الحياة الواقعية: تخيل وجود مخزن مؤقت للطابعة حيث يجب على مثيل واحد فقط إدارة جميع مهام الطباعة.

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