📜  OOAD-面向对象范例(1)

📅  最后修改于: 2023-12-03 15:18:06.983000             🧑  作者: Mango

OOAD-面向对象范例

面向对象分析与设计(Object Oriented Analysis and Design,简称OOAD)是一种软件工程方法,旨在通过对象和类的概念来分析和设计系统。本文将介绍一些面向对象范例,帮助程序员更好地理解OOAD。

示例1:图书管理系统

首先,我们来看一个图书管理系统的例子。该系统需要实现以下功能:

  1. 用户能登录/注销账户;
  2. 用户能查看所有的书籍;
  3. 用户能查看已借出的书籍;
  4. 用户能根据书名、作者或ISBN号查找书籍;
  5. 用户能借阅/归还书籍;
  6. 管理员能添加/删除书籍;
  7. 管理员能查看所有用户的借阅记录。

对于该系统,我们可以设计以下类:

User类
public class User {
    private String name;
    private String password;
    private List<Book> borrowedBooks;

    public User(String name, String password) {
        this.name = name;
        this.password = password;
        this.borrowedBooks = new ArrayList<>();
    }

    public String getName() {
        return name;
    }

    public boolean checkPassword(String password) {
        return this.password.equals(password);
    }

    public void borrowBook(Book book) {
        borrowedBooks.add(book);
    }

    public void returnBook(Book book) {
        borrowedBooks.remove(book);
    }

    public List<Book> getBorrowedBooks() {
        return borrowedBooks;
    }
}
Book类
public class Book {
    private String title;
    private String author;
    private String isbn;
    private boolean borrowed;

    public Book(String title, String author, String isbn) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
        this.borrowed = false;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getIsbn() {
        return isbn;
    }

    public boolean isBorrowed() {
        return borrowed;
    }

    public void borrow() {
        borrowed = true;
    }

    public void returnBook() {
        borrowed = false;
    }
}
Library类
public class Library {
    private List<User> users;
    private List<Book> books;

    public Library() {
        users = new ArrayList<>();
        books = new ArrayList<>();
    }

    public void addUser(User user) {
        users.add(user);
    }

    public void removeUser(User user) {
        users.remove(user);
    }

    public User getUser(String name) {
        for (User user : users) {
            if (user.getName().equals(name)) {
                return user;
            }
        }
        return null;
    }

    public void addBook(Book book) {
        books.add(book);
    }

    public void removeBook(Book book) {
        books.remove(book);
    }

    public List<Book> search(String keyword) {
        List<Book> result = new ArrayList<>();
        for (Book book : books) {
            if (book.getTitle().contains(keyword) ||
                book.getAuthor().contains(keyword) ||
                book.getIsbn().contains(keyword)) {
                result.add(book);
            }
        }
        return result;
    }

    public void lendBook(Book book, User user) {
        if (!book.isBorrowed()) {
            book.borrow();
            user.borrowBook(book);
        }
    }

    public void returnBook(Book book, User user) {
        if (book.isBorrowed()) {
            book.returnBook();
            user.returnBook(book);
        }
    }

    public List<Book> getBooks() {
        return books;
    }

    public List<User> getUsers() {
        return users;
    }
}
示例2:物理引擎

我们再来看一个物理引擎的例子。该引擎需要支持以下功能:

  1. 计算物体在重力下的运动轨迹;
  2. 计算物体在弹性碰撞中的反弹轨迹;
  3. 支持多个物体之间的碰撞检测。

对于该引擎,我们可以设计以下类:

Vector2D类
public class Vector2D {
    private double x;
    private double y;

    public Vector2D(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }

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

    public double getY() {
        return y;
    }

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

    public double getLength() {
        return Math.sqrt(x * x + y * y);
    }

    public Vector2D normalize() {
        double length = getLength();
        return new Vector2D(x / length, y / length);
    }

    public Vector2D add(Vector2D other) {
        return new Vector2D(x + other.x, y + other.y);
    }

    public Vector2D subtract(Vector2D other) {
        return new Vector2D(x - other.x, y - other.y);
    }

    public Vector2D multiply(double scalar) {
        return new Vector2D(x * scalar, y * scalar);
    }

    public double dot(Vector2D other) {
        return x * other.x + y * other.y;
    }

    public Vector2D project(Vector2D direction) {
        double dot = dot(direction);
        double length = direction.getLength();
        return direction.multiply(dot / (length * length));
    }

    public Vector2D reflect(Vector2D normal) {
        Vector2D incident = normalize();
        Vector2D reflected = incident.subtract(normal.multiply(2 * incident.dot(normal)));
        return reflected;
    }
}
Particle类
public class Particle {
    private Vector2D position;
    private Vector2D velocity;
    private Vector2D acceleration;
    private double mass;

    public Particle(Vector2D position, Vector2D velocity, Vector2D acceleration, double mass) {
        this.position = position;
        this.velocity = velocity;
        this.acceleration = acceleration;
        this.mass = mass;
    }

    public Vector2D getPosition() {
        return position;
    }

    public void setPosition(Vector2D position) {
        this.position = position;
    }

    public Vector2D getVelocity() {
        return velocity;
    }

    public void setVelocity(Vector2D velocity) {
        this.velocity = velocity;
    }

    public Vector2D getAcceleration() {
        return acceleration;
    }

    public void setAcceleration(Vector2D acceleration) {
        this.acceleration = acceleration;
    }

    public double getMass() {
        return mass;
    }

    public void setMass(double mass) {
        this.mass = mass;
    }

    public void move(double dt) {
        Vector2D delta = velocity.multiply(dt);
        position = position.add(delta);
    }

    public void update(double dt) {
        Vector2D deltaV = acceleration.multiply(dt);
        velocity = velocity.add(deltaV);

        Vector2D deltaP = velocity.multiply(dt);
        position = position.add(deltaP);
    }

    public void applyForce(Vector2D force) {
        Vector2D deltaA = force.multiply(1 / mass);
        acceleration = acceleration.add(deltaA);
    }

    public void bounceOff(Particle other) {
        Vector2D normal = other.getPosition().subtract(position).normalize();
        Vector2D v1n = normal.project(velocity);
        Vector2D v1t = velocity.subtract(v1n);
        Vector2D v2n = normal.project(other.getVelocity());
        Vector2D v2t = other.getVelocity().subtract(v2n);

        Vector2D v1nNew = v2n;
        Vector2D v2nNew = v1n;

        Vector2D v1New = v1nNew.add(v1t);
        Vector2D v2New = v2nNew.add(v2t);

        velocity = v1New;
        other.setVelocity(v2New);
    }
}
Collision类
public class Collision {
    private Particle particle1;
    private Particle particle2;
    private double time;

    public Collision(Particle particle1, Particle particle2, double time) {
        this.particle1 = particle1;
        this.particle2 = particle2;
        this.time = time;
    }

    public Particle getParticle1() {
        return particle1;
    }

    public Particle getParticle2() {
        return particle2;
    }

    public double getTime() {
        return time;
    }
}
ParticleSystem类
public class ParticleSystem {
    private List<Particle> particles;

    public ParticleSystem(List<Particle> particles) {
        this.particles = particles;
    }

    public List<Particle> getParticles() {
        return particles;
    }

    public void move(double dt) {
        for (Particle particle : particles) {
            particle.move(dt);
        }
    }

    public List<Collision> detectCollisions() {
        List<Collision> collisions = new ArrayList<>();
        for (int i = 0; i < particles.size(); i++) {
            Particle particle1 = particles.get(i);
            for (int j = i + 1; j < particles.size(); j++) {
                Particle particle2 = particles.get(j);
                double time = predictCollisionTime(particle1, particle2);
                if (time >= 0 && time <= 1) {
                    collisions.add(new Collision(particle1, particle2, time));
                }
            }
        }
        return collisions;
    }

    public void handleCollisions(List<Collision> collisions) {
        for (Collision collision : collisions) {
            Particle particle1 = collision.getParticle1();
            Particle particle2 = collision.getParticle2();
            double time = collision.getTime();

            particle1.update(time);
            particle2.update(time);

            particle1.bounceOff(particle2);
        }
    }

    public double predictCollisionTime(Particle particle1, Particle particle2) {
        Vector2D deltaR = particle2.getPosition().subtract(particle1.getPosition());
        Vector2D deltaV = particle2.getVelocity().subtract(particle1.getVelocity());
        double sigma = particle1.getMass() + particle2.getMass();
        double r = particle1.getRadius() + particle2.getRadius();

        double a = deltaV.getLengthSquared();
        double b = 2 * deltaR.dot(deltaV);
        double c = deltaR.getLengthSquared() - r * r;

        double delta = b * b - 4 * a * c;

        if (delta >= 0) {
            double time1 = (-b - Math.sqrt(delta)) / (2 * a);
            double time2 = (-b + Math.sqrt(delta)) / (2 * a);
            if (time1 >= 0 && time1 <= 1) {
                return time1;
            } else if (time2 >= 0 && time2 <= 1) {
                return time2;
            } else {
                return -1;
            }
        } else {
            return -1;
        }
    }
}
总结

本文介绍了两个面向对象的范例,一个是图书管理系统,另一个是物理引擎。通过这些例子,我们可以看到面向对象的思想在实际开发中的应用。在设计类时,需要考虑类的属性和方法,并且要把类的职责分配清楚。只有设计出良好的类,才能写出易于维护、可复用的代码。