CodeGym /Kurslar /JAVA 25 SELF /Real tapşırıqlarda abstraksiyaların qurulması nümunələri

Real tapşırıqlarda abstraksiyaların qurulması nümunələri

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Real tətbiqlərdə abstraksiya: nə üçün lazımdır

Ötən mühazirələrdə artıq abstraksiya anlayışı ilə tanış olmuş və sadə nümunələrə baxmışdıq. İndi isə bu yanaşmanın daha real tapşırıqlarda necə işlədiyini görəcəyik. Real layihələrdə demək olar ki, həmişə bir-birinə bənzəyən, amma fərqli obyektlərlə işləmək lazım gəlir. Məsələn, müxtəlif ödəniş üsulları, müxtəlif nəqliyyat növləri, qrafik redaktorda müxtəlif fiqurlar. Abstraksiya tətbiq edilməzsə, kod tez bir zamanda if-else “budaqlarının” və kopi-pastın yığınlığına çevrilir. Abstraksiya ilə isə hər şey səliqəli, sistemli və ən əsası, inkişaf və dəstək üçün əlverişli olur.

Abstraksiya imkan verir ki:

  • Reallaşdırma detallarını gizlədək: obyektlərlə onların daxili quruluşunu bilmədən ümumi interfeys vasitəsilə işləmək.
  • Kodun təkrarlanmasından qaçaq: ümumi davranış və sahələr (fields) baza sinfə çıxarılır.
  • Sistemi asanlıqla genişləndirək: yeni obyekt növü əlavə etmək köhnə kodun yenidən yazılmasını tələb etmir.
  • Kodu çevik edək: sistemin qalan hissəsini dəyişmədən bir reallaşdırmanı digəri ilə əvəz etmək olar.

Gəlin müxtəlif sahələrdən bir neçə nümunəyə baxaq.

2. Nümunə 1: Ödəniş sistemləri

Tapşırığın tərifi

Tutaq ki, siz internet mağaza üçün modul yazırsınız. Tapşırığınız — müxtəlif ödəniş növlərinin emalını həyata keçirməkdir: bank kartı, PayPal, kriptovalyuta. Hamısı “ödənişi emal etməyi” bacarmalıdır, amma hər birinin detalları fərqlidir.

Abstraksiya: Payment sinfi

public abstract class Payment {
    protected double amount;

    public Payment(double amount) {
        this.amount = amount;
    }

    // Abstrakt metod: ödənişin necə emal olunacağını törəmə siniflər müəyyənləşdirir
    public abstract void process();

    // Bütün ödənişlər üçün ümumi metod
    public void printAmount() {
        System.out.println("Ödəniş məbləği: " + amount + " rubl.");
    }
}

Konkret reallaşdırmalar

public class CreditCardPayment extends Payment {
    private String cardNumber;

    public CreditCardPayment(double amount, String cardNumber) {
        super(amount);
        this.cardNumber = cardNumber;
    }

    @Override
    public void process() {
        System.out.println("Kart üzrə ödənişin emalı: " + cardNumber);
        // Burada bank inteqrasiyası ola bilərdi :)
    }
}
public class PaypalPayment extends Payment {
    private String email;

    public PaypalPayment(double amount, String email) {
        super(amount);
        this.email = email;
    }

    @Override
    public void process() {
        System.out.println("Hesab üçün PayPal ödənişinin emalı: " + email);
        // Və burada PayPal API çağırışı
    }
}
public class CryptoPayment extends Payment {
    private String walletAddress;

    public CryptoPayment(double amount, String walletAddress) {
        super(amount);
        this.walletAddress = walletAddress;
    }

    @Override
    public void process() {
        System.out.println("Kripto ödənişinin cüzdana emalı: " + walletAddress);
        // Burada blokçeyn sehrləri ola bilərdi
    }
}

Abstraksiyadan istifadə

import java.util.*;

public class PaymentDemo {
    public static void main(String[] args) {
        List<Payment> payments = new ArrayList<>();
        payments.add(new CreditCardPayment(1500.0, "1234 5678 9012 3456"));
        payments.add(new PaypalPayment(500.0, "user@example.com"));
        payments.add(new CryptoPayment(0.05, "0xABCD..."));

        for (Payment payment : payments) {
            payment.printAmount();
            payment.process();
            System.out.println("---");
        }
    }
}

İşin nəticəsi:

Ödəniş məbləği: 1500.0 rubl.
Kart üzrə ödənişin emalı: 1234 5678 9012 3456
---
Ödəniş məbləği: 500.0 rubl.
Hesab üçün PayPal ödənişinin emalı: user@example.com
---
Ödəniş məbləği: 0.05 rubl.
Kripto ödənişinin cüzdana emalı: 0xABCD...
---

Üstünlüklər:

  • Yeni ödəniş üsulunu köhnə kodu dəyişmədən əlavə etmək olar (məsələn, Apple Pay).
  • Ödənişlərlə işləyən kod onların konkret tipindən asılı deyil.
  • Ümumi məntiq (məsələn, məbləğin printAmount() vasitəsilə çapı) bir yerdə reallaşdırılıb.

3. Nümunə 2: Nəqliyyat

Tapşırığın tərifi

Oyunda və ya simulatorda müxtəlif nəqliyyat növləriniz var: maşınlar, velosipedlər, qatarlar. Hamısı “hərəkət edə” bilir, lakin bunu müxtəlif cür edir. Bəzilərinin yanacağa ehtiyacı var, bəzilərinin isə yoxdur.

Abstraksiya: Transport sinfi

public abstract class Transport {
    protected String name;

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

    public abstract void move();

    // Hər nəqliyyat növünün yanacağa ehtiyacı olmaya bilər, susmaya görə - ehtiyac yoxdur
    public void fuelUp() {
        System.out.println(name + ": yanacağa ehtiyac yoxdur.");
    }
}

Konkret reallaşdırmalar

public class Car extends Transport {
    public Car(String name) {
        super(name);
    }

    @Override
    public void move() {
        System.out.println(name + " yolda gedir.");
    }

    @Override
    public void fuelUp() {
        System.out.println(name + ": benzinlə doldururuq.");
    }
}
public class Bicycle extends Transport {
    public Bicycle(String name) {
        super(name);
    }

    @Override
    public void move() {
        System.out.println(name + " pedal çevirir.");
    }
    // fuelUp metodunu yenidən yazmırıq — velosipedə yanacaq lazım deyil
}
public class Train extends Transport {
    public Train(String name) {
        super(name);
    }

    @Override
    public void move() {
        System.out.println(name + " relslərdə sürətli hərəkət edir.");
    }

    @Override
    public void fuelUp() {
        System.out.println(name + ": dizellə və ya elektriklə təmin edirik.");
    }
}

Abstraksiyadan istifadə

import java.util.*;

public class TransportDemo {
    public static void main(String[] args) {
        List<Transport> vehicles = Arrays.asList(
            new Car("Toyota"),
            new Bicycle("Stels"),
            new Train("Sapsan")
        );

        for (Transport t : vehicles) {
            t.move();
            t.fuelUp();
            System.out.println("---");
        }
    }
}

İşin nəticəsi:

Toyota yolda gedir.
Toyota: benzinlə doldururuq.
---
Stels pedal çevirir.
Stels: yanacağa ehtiyac yoxdur.
---
Sapsan relslərdə sürətli hərəkət edir.
Sapsan: dizellə və ya elektriklə təmin edirik.
---

Üstünlüklər:

  • Tipini yoxlamadan istənilən nəqliyyatla eyni cür işləmək olar.
  • Yeni nəqliyyat növünü (məsələn, elektrik skuterini) asanlıqla əlavə etmək olar.

4. Nümunə 3: Qrafik redaktor

Tapşırığın tərifi

Siz mini qrafik redaktor yazırsınız. Burada xətlər, ellipslər, çoxbucaqlılar var — və bunların hamısı “fiqur”lardır; çəkilə və ölçüsü dəyişdirilə bilər. Hər fiqur bu əməliyyatları özünəməxsus şəkildə həyata keçirir.

Abstraksiya: Figure sinfi

public abstract class Figure {
    protected String color = "black";

    public abstract void draw();

    public abstract void resize(double factor);

    public void setColor(String color) {
        this.color = color;
    }
}

Konkret reallaşdırmalar

public class Line extends Figure {
    private double length;

    public Line(double length) {
        this.length = length;
    }

    @Override
    public void draw() {
        System.out.println("Uzunluğu " + length + " olan xətt çəkirik, rəngi " + color);
    }

    @Override
    public void resize(double factor) {
        length *= factor;
        System.out.println("Xəttin yeni uzunluğu: " + length);
    }
}
public class Ellipse extends Figure {
    private double a, b;

    public Ellipse(double a, double b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void draw() {
        System.out.println("Oxları " + a + " və " + b + " olan ellips çəkirik, rəngi " + color);
    }

    @Override
    public void resize(double factor) {
        a *= factor;
        b *= factor;
        System.out.println("Ellipsin yeni ölçüləri: " + a + " x " + b);
    }
}
public class Polygon extends Figure {
    private int sides;

    public Polygon(int sides) {
        this.sides = sides;
    }

    @Override
    public void draw() {
        System.out.println(sides + " tərəfli çoxbucaqlı çəkirik, rəngi " + color);
    }

    @Override
    public void resize(double factor) {
        System.out.println(sides + " tərəfli çoxbucaqlının ölçüsünü " + factor + " dəfə dəyişirik");
    }
}

Abstraksiyadan istifadə

import java.util.*;

public class EditorDemo {
    public static void main(String[] args) {
        List<Figure> figures = new ArrayList<>();
        figures.add(new Line(10));
        figures.add(new Ellipse(5, 3));
        figures.add(new Polygon(6));

        for (Figure f : figures) {
            f.setColor("green");
            f.draw();
            f.resize(2);
            System.out.println("---");
        }
    }
}

İşin nəticəsi:

Uzunluğu 10.0 olan xətt çəkirik, rəngi green
Xəttin yeni uzunluğu: 20.0
---
Oxları 5.0 və 3.0 olan ellips çəkirik, rəngi green
Ellipsin yeni ölçüləri: 10.0 x 6.0
---
6 tərəfli çoxbucaqlı çəkirik, rəngi green
6 tərəfli çoxbucaqlının ölçüsünü 2.0 dəfə dəyişirik
---

Üstünlüklər:

  • Bütün fiqurları bir siyahıda saxlamaq və eyni qaydada emal etmək olar.
  • Yeni fiquru (məsələn, ulduz və ya ürək) asanlıqla əlavə etmək olar.
  • Ümumi metodlar (məsələn, rəngin setColor() ilə qurulması) bir dəfə reallaşdırılır.

5. Abstraksiya kodu necə sadələşdirir

Yuxarıdakı hər nümunədə ümumi bir sxem var:

  • Baza abstrakt sinif müqaviləni müəyyənləşdirir (obyekt nə edə bilir).
  • Konkret varislər detalları reallaşdırır.
  • Abstraksiya ilə işləyən kod obyektin tipindən asılı deyil; bu da sistemi çevik və genişlənə bilən edir.

Yanaşmaların müqayisə cədvəli

Abstraksiyasız (if-else) Abstraksiya ilə (OOP)
Tipə görə çoxlu şərt Yeni tip — kodu dəyişirik
Məntiqin təkrarlanması Məntiq — bir yerdə
Genişləndirmək çətindir Əlavə etmək — asandır
Sınaqdan keçirmək çətindir Reallaşdırmaları asanlıqla əvəzləmək olar

6. Abstraksiyaların layihələndirilməsində tipik səhvlər

Səhv №1: Abstraksiya naminə abstraksiya.
Əgər cəmi bir obyekt tipiniz var və genişlənmə planlaşdırılmırsa — abstrakt sinfə ehtiyac yoxdur. Kodu səbəbsiz yerə mürəkkəbləşdirməyin.

Səhv №2: Həddən artıq ümumi abstraksiya.
Baza sinif çox “bulanıqdırsa”, varislərin adından başqa ortaq cəhəti olmaya bilər. Məsələn, hər şey üçün “Thing” abstraksiyası. Bu, dəstəyi və kodun başa düşülməsini çətinləşdirir.

Səhv №3: Varislərdə kod təkrarı.
Əgər bütün varislərdə metod eyni cür reallaşdırılıbsa, onu baza sinfə çıxarmağa dəyər (abstrakt etməmək).

Səhv №4: “Ümundan xüsusiyə” prinsipinin pozulması.
Əgər abstrakt sinifdə yalnız bir varisə lazım olan detallar peyda olursa — deməli, seçilən abstraksiya yanlışdır.

Səhv №5: Abstrakt metodların reallaşdırılmasını unutmaq.
Əgər varisdə bütün abstrakt metodlar reallaşdırılmasa, kompilyator sinfi də abstrakt etməyə məcbur edəcək. Bəzən bu, gözlənilməz olur :)

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Qrafik tətbiqdə sahə hesablamaları 🎨
Qrafik tətbiqdə sahə hesablamaları 🎨
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Universal bildirişlər göndərmə sistemi 📧💬
Universal bildirişlər göndərmə sistemi 📧💬
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Şirkətin nəqliyyat parkının idarə edilməsi 🚚🚲
Şirkətin nəqliyyat parkının idarə edilməsi 🚚🚲
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Pərakəndə mağazada sifarişlərin işlənməsi modulu 🛒
Pərakəndə mağazada sifarişlərin işlənməsi modulu 🛒
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION