首页 > 其他分享 >面向对象与设计模式第一课:深入理解OOP

面向对象与设计模式第一课:深入理解OOP

时间:2024-10-21 08:49:09浏览次数:9  
标签:const 示例 void class 第一课 Shape OOP 设计模式 public

第三章:面向对象与设计模式

第一课:深入理解OOP

面向对象编程(OOP)是一种编程范式,它将程序结构视为由对象组成,促进了代码的重用性和可维护性。在这一课中,我们将深入分析OOP的四个基本特性:封装、继承、多态和抽象,并提供相应的示例与实践。

1. OOP基本特性
1.1 封装

封装是OOP的核心概念之一,它指的是将对象的状态(属性)和行为(方法)组合在一起,同时隐藏内部实现细节,只暴露必要的接口。这使得对象可以保护自己的数据不被外部干扰,从而提高了代码的安全性和稳定性。

示例

class BankAccount {
private:
    double balance; // 账户余额

public:
    BankAccount(double initial_balance) : balance(initial_balance) {}

    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }

    double getBalance() const {
        return balance;
    }
};

在上面的示例中,balance属性被声明为私有(private),外部代码无法直接访问。只有通过公共方法(depositwithdrawgetBalance),才能修改或获取余额。

1.2 继承

继承允许一个类从另一个类派生,从而获得其属性和行为。这种机制支持代码重用和逻辑结构的组织,使得程序设计更加灵活。

示例

class SavingsAccount : public BankAccount {
private:
    double interestRate; // 利率

public:
    SavingsAccount(double initial_balance, double rate)
        : BankAccount(initial_balance), interestRate(rate) {}

    void applyInterest() {
        deposit(getBalance() * interestRate);
    }
};

在这个例子中,SavingsAccount类继承自BankAccount类,得到了其所有的属性和方法,并增加了一个新的方法applyInterest,用于计算利息。

1.3 多态

多态允许对象以不同的形式表现。这意味着可以使用同一接口来处理不同类型的对象。这通常通过虚函数实现,使得程序可以在运行时选择调用哪个函数。

示例

class Shape {
public:
    virtual void draw() const = 0; // 纯虚函数
};

class Circle : public Shape {
public:
    void draw() const override {
        // 画圆的逻辑
    }
};

class Rectangle : public Shape {
public:
    void draw() const override {
        // 画矩形的逻辑
    }
};

void render(const Shape& shape) {
    shape.draw(); // 动态调用
}

在这个示例中,Shape是一个基类,定义了一个纯虚函数drawCircleRectangle类实现了这个函数。通过传递Shape引用,render函数能够根据实际对象类型动态调用相应的draw方法。

1.4 抽象

抽象是指通过提取对象的共同特征来创建类。抽象类通常包含纯虚函数,无法实例化。它们提供了一个模板,其他类可以从中继承并实现特定的功能。

示例

class Animal {
public:
    virtual void makeSound() const = 0; // 抽象方法
};

class Dog : public Animal {
public:
    void makeSound() const override {
        // 狗叫的逻辑
    }
};

class Cat : public Animal {
public:
    void makeSound() const override {
        // 猫叫的逻辑
    }
};

在这个例子中,Animal是一个抽象类,定义了一个纯虚函数makeSoundDogCat类实现了这个函数,表示它们各自的叫声。

2. 类的设计原则与实际案例

设计原则帮助开发者编写可维护、可扩展和可重用的代码。以下是几个常用的设计原则:

2.1 单一职责原则(SRP)

一个类应该只有一个单一的职责,所有的功能都应该围绕这个职责展开。这可以减少类的复杂性,便于维护和修改。

示例

class User {
public:
    void login() {
        // 登录逻辑
    }
};

class UserNotifier {
public:
    void notifyUser() {
        // 通知用户逻辑
    }
};

在这个示例中,User类负责用户登录,而UserNotifier类负责用户通知。两个类各司其职,符合单一职责原则。

2.2 开放封闭原则(OCP)

软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着可以通过添加新代码而不是修改现有代码来实现新功能。

示例

class Shape {
public:
    virtual double area() const = 0; // 纯虚函数
};

class Circle : public Shape {
public:
    double area() const override {
        // 计算圆的面积
    }
};

class Rectangle : public Shape {
public:
    double area() const override {
        // 计算矩形的面积
    }
};

// 新增多边形类
class Polygon : public Shape {
public:
    double area() const override {
        // 计算多边形的面积
    }
};

在这个例子中,新增的Polygon类并没有修改现有的代码,而是通过继承Shape类实现新的功能,符合开放封闭原则。

2.3 里氏替换原则(LSP)

子类对象应该能够替换父类对象,而不会影响程序的正确性。这意味着子类必须符合父类的约定。

示例

void drawShape(const Shape& shape) {
    shape.draw(); // 可以接受任何形状的子类
}

确保CircleRectangle等子类都能正确执行父类的方法,不会引入错误。

2.4 接口隔离原则(ISP)

不应强迫客户依赖于他们不使用的接口。接口应该细化为特定的、功能单一的接口。

示例

class IShape {
public:
    virtual void draw() const = 0;
};

class IColor {
public:
    virtual void fill() const = 0;
};

class Circle : public IShape, public IColor {
public:
    void draw() const override {
        // 画圆的逻辑
    }

    void fill() const override {
        // 填充圆的逻辑
    }
};

在这个例子中,IShapeIColor接口分别定义了不同的功能,避免了客户不必要的依赖。

2.5 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,二者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。

示例

class Notification {
public:
    virtual void send() = 0; // 抽象通知
};

class EmailNotification : public Notification {
public:
    void send() override {
        // 发送电子邮件逻辑
    }
};

class SmsNotification : public Notification {
public:
    void send() override {
        // 发送短信逻辑
    }
};

class User {
    Notification* notifier;

public:
    User(Notification* n) : notifier(n) {}

    void notify() {
        notifier->send(); // 使用抽象发送通知
    }
};

在这个示例中,User类依赖于Notification接口而不是具体的通知实现,从而实现了依赖倒置原则。

3. 项目实践

在实际项目中,运用OOP的特性和设计原则是非常重要的。下面是一个基于OOP的简单项目示例。

3.1 项目背景

我们要创建一个简单的图形编辑器,能够支持绘制多种形状并计算其面积。通过OOP的特性,我们可以设计出灵活且易于扩展的结构。

3.2 类的设计
  • Shape类作为抽象基类,定义绘制和计算面积的方法。
  • 具体的形状类(如CircleRectangle)继承自Shape并实现相关方法。
  • ShapeManager类负责管理所有形状,提供添加、删除和遍历功能。
3.3 代码示例
#include <iostream>
#include <vector>
#include <memory>

class Shape {
public:
    virtual void draw() const = 0;
    virtual double area() const = 0;
    virtual ~Shape() = default; // 虚析构函数
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    void draw() const override {
        std::cout << "Drawing Circle with radius: " << radius << std::endl;
    }

    double area() const override {
        return 3.14 * radius * radius;
    }
};

class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    void draw() const override {
        std::cout << "Drawing Rectangle with width: " << width << " and height: " << height << std::endl;
    }

    double area() const override {
        return width * height;
    }
};

class ShapeManager {
private:
    std::vector<std::shared_ptr<Shape>> shapes;

public:
    void addShape(std::shared_ptr<Shape> shape) {
        shapes.push_back(shape);
    }

    void drawAll() const {
        for (const auto& shape : shapes) {
            shape->draw();
        }
    }

    void calculateTotalArea() const {
        double totalArea = 0;
        for (const auto& shape : shapes) {
            totalArea += shape->area();
        }
        std::cout << "Total Area: " << totalArea << std::endl;
    }
};

int main() {
    ShapeManager manager;
    manager.addShape(std::make_shared<Circle>(5.0));
    manager.addShape(std::make_shared<Rectangle>(4.0, 6.0));

    manager.drawAll();
    manager.calculateTotalArea();

    return 0;
}

在这个简单的图形编辑器项目中,我们通过OOP的特性和设计原则,实现了一个可扩展的框架。将来可以很方便地添加新的形状类,而无需修改现有代码。

总结

本课深入探讨了面向对象编程的基本特性,包括封装、继承、多态和抽象,以及如何应用这些特性设计出符合OOP原则的类。在实际开发中,遵循设计原则有助于编写可维护、可扩展的代码。通过简单的项目实例,我们展示了OOP在实际中的应用,帮助初级到中级程序员更好地理解和应用OOP的理念。

标签:const,示例,void,class,第一课,Shape,OOP,设计模式,public
From: https://blog.csdn.net/u012263104/article/details/143103417

相关文章

  • 05 设计模式-创造型模式-原型模式
    原型模式(PrototypePattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在......
  • HOOPS SDK 2024.7.0
    使用HOOPSExchangeSDK进行CAD数据转换,将30多种CAD文件格式导入您的应用程序,通过单一API即可快速准确地读取和写入2D和3DCAD文件格式,包括CATIA®、SOLIDWORKS®、Inventor™、Revit™、Creo®、NX™、SolidEdge®等。HOOPSCommunicator图形引擎可加速We......
  • 【设计模式系列】命令模式
    目录一、什么是命令模式二、命令模式的角色三、命令模式的典型应用场景四、命令模式在Runnable中的应用一、什么是命令模式命令模式(CommandPattern)是一种行为设计模式,它将一个请求或简单操作封装为一个对象。这个模式提供了一种机制,使得你可以将操作的发出者(发起请求......
  • Java设计模式——适配器模式
    适配器模式(AdapterPattern)是一种结构型设计模式,它用于将一个类的接口转换成客户端希望的另一个接口,使得原本由于接口不兼容而无法一起工作的类可以协同工作。适配器模式的主要目的是兼容性和重用性,特别是在使用一些已有的类,而它们的接口又不符合要求时。适配器模式的核心思想......
  • java_day19_线程组、线程池、定时器、InetAddress、网络编程、设计模式
    一、线程组:线程组:将属于同一类的线程划分到同一组中,可以直接对线程组进行设置。ThreadGroup构造方法:ThreadGroup(Stringname)构造一个新的线程组。代码案例:classMyThread1extendsThread{publicMyThread1(){}publicMyThread1(ThreadGr......
  • Java设计模式之单例模式学习
    单例模式目录单例模式1.饿汉式(线程安全)2.懒汉式(线程不安全)3.懒汉式(线程安全)4.双重检查锁定(Double-CheckedLocking)5.静态内部类6.枚举Java中的单例模式(SingletonPattern)是一种常用的设计模式,其目的是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。单例模......
  • Golang 常用的五种创建型设计模式
    Golang常用的五种创建型设计模式原创GoOfficialBlogGoOfficialBlog 2024年10月18日19:10中国香港听全文在Go中,创建设计模式有助于管理对象的创建,并控制对象的实例化方式。这些模式在对象创建过程复杂或需要特殊处理时特别有用。以下是Go中常用的主要创建模式: ......
  • 策略模式是一种行为设计模式
    策略模式是一种行为设计模式,允许你定义一系列算法、封装每一个算法,并使它们可以相互替换。策略模式使得算法的变化独立于使用算法的客户端。以下是一个用策略模式实现不同类型促销活动的Java示例。步骤定义促销策略接口:创建一个接口,定义促销活动的方法。实现具体策略:......
  • 前端开发设计模式——状态模式
    目录一、状态模式的定义和特点二、状态模式的结构与原理1.结构:2.原理:三、状态模式的实现方式四、状态模式的使用场景1.按钮的不同状态:2.页面加载状态:3.用户登录状态:五、状态模式的优点1.提高代码的可维护性:2.增强代码的可读性:3.更好的处理动态变化:六、状态模式的......
  • 【设计模式】适配器模式
    设计模式【设计模式】工厂方法模式【设计模式】抽象工厂模式【设计模式】单例模式【设计模式】策略模式【设计模式】观察者模式【设计模式】装饰模式【设计模式】适配器模式 一、介绍适配器模式是一种结构型设计模式,它能使接口不兼容的对象能够相互合作。适配器可......