设计模式->如何抽象出对象

这里说对象,而不说类,是因为我们总是先发现了对象,然后抽象出类的。绝不是相反的,不然很别扭,很不符合认知习惯。你要教你小孩鸟类这个概念你总不会说世界一种鸟类,有翅膀、有羽毛,会飞。看这就是鸟。你想你小孩会怎样,一脸蒙逼,但是你拿个模型呢,或者去宠物市场呢,看到一只鸟,再和你小孩讲解鸟类就容易很多。

那么两者的关系呢,个人理解从对象抽象出类,从类具象化为对象。在代码层面上先发现对象,然后定义类,然后使用对象来交互,从而形成代码。

那门如何发现对象呢,这里自己一个方法,就是找名词、找动词,这个也是我一个同事教会我的,希望对你有点帮助。

 

例如:有一只鸟,有羽毛、有翅膀、会飞、会吃东西

那么名词:鸟,羽毛,翅膀,

那么动词:飞、吃东西

 

那么就很好抽象了,鸟、羽毛、翅膀都是名词,都可能是对象,那么为什么羽毛和翅膀为什么有的人认为是属性呢,其实属性和对象很难区分,如果非要区分,我认为是作用域,这里我们研究鸟,我们将羽毛翅膀当成属性了,那天我们要详细研究了,抽象出羽毛类,那门羽毛可以认为是一个对象,注入到鸟的对象中来。

那么飞、吃东西就是行为了,就是鸟这对象的方法

再进一步,我们就抽象出了鸟类,有羽毛和翅膀属性,有飞和吃东西的方法。再进一步呢,猫有毛,猫会吃东西,共同点找到了,再抽象呢,就抽象出父类野兽了。缩小范围,会飞,是野兽吗,当然不是,不是所有的野兽都会飞。是鸟吗,可以这么说,鸟都会飞,但是只有鸟会飞吗,显然不是,飞机也会飞,蝙蝠也会飞,那么怎么理解呢,为什么不能再抽象的基础上再抽象下呢,不仅仅是抽象事务,我们抽象了行为,这就是接口的产生了,接口是行为的抽象,具体到这个例子就是飞这个动作的抽象,将这个抽象出接口,是JAVA的通用做法,当然你也可以用多继承,使用虚函数解决,这个是另外一个思路,看成是C++的解决方式了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下一个可能的重构方案: 1. 单一职责原则:将文件读写和书籍管理分离成两个类,`FileManager` 和 `BookManager`。 ```c++ class FileManager { public: virtual ~FileManager() {} virtual void write(const std::string& filename, const std::vector<std::string>& lines) = 0; virtual std::vector<std::string> read(const std::string& filename) = 0; }; class BookManager { public: virtual ~BookManager() {} virtual bool addBook(const std::string& name, const std::string& author, const std::string& num, int instock) = 0; virtual std::vector<Book*> getBooks() = 0; }; ``` 2. 依赖倒置原则:将 `Library` 类中的文件读写操作抽象成 `FileManager` 接口,并将其作为 `Library` 的构造函数参数传入。 ```c++ class Library { public: Library(FileManager* fileManager, BookManager* bookManager); bool addBook(const std::string& name, const std::string& author, const std::string& num, int instock); void printBooks(); private: FileManager* fileManager_; BookManager* bookManager_; }; ``` 3. 开闭原则:使用工厂模式来创建 `Book` 对象,以便将来添加或删除书籍信息的属性时不需要修改 `Book` 类。 ```c++ class BookFactory { public: static Book* create(const std::string& name, const std::string& author, const std::string& num, int instock); }; ``` 4. 代码坏味道:将文件读写操作抽象成独立的函数,并将其封装在 `FileManager` 类中。 ```c++ class TextFileManager : public FileManager { public: void write(const std::string& filename, const std::vector<std::string>& lines) override; std::vector<std::string> read(const std::string& filename) override; }; void TextFileManager::write(const std::string& filename, const std::vector<std::string>& lines) { std::ofstream f(filename); for (const auto& line : lines) { f << line << std::endl; } } std::vector<std::string> TextFileManager::read(const std::string& filename) { std::ifstream f(filename); std::vector<std::string> lines; std::string line; while (std::getline(f, line)) { lines.push_back(line); } return lines; } ``` 重构后的 `Library` 类中的 `addBook()` 和 `printBooks()` 函数的实现如下: ```c++ bool Library::addBook(const std::string& name, const std::string& author, const std::string& num, int instock) { bool success = bookManager_->addBook(name, author, num, instock); if (success) { std::vector<std::string> lines; for (const auto& book : bookManager_->getBooks()) { lines.push_back(book->getName() + " " + book->getAuthor() + " " + book->getNum() + " " + std::to_string(book->getInstock())); } fileManager_->write("books.txt", lines); } return success; } void Library::printBooks() { std::vector<std::string> lines = fileManager_->read("books.txt"); for (const auto& line : lines) { std::istringstream iss(line); std::string name, author, num; int instock; iss >> name >> author >> num >> instock; std::cout << name << " " << author << " " << num << " " << instock << std::endl; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值