5分钟学设计模式:简单工厂与美食街的不期而遇

大家好,我是知微。

写代码好几年,是不是还纠结于这些问题:

  • 面对一堆if-else,代码越写越长,维护起来比攀登珠穆朗玛峰还难
  • 每次只敢小心翼翼改个小功能,生怕程序突然“嘭”一声,全炸了
  • 想学习大佬们的代码,却总是看得一头雾水,不知如何下手。

别急,优秀的代码设计往往有秘诀——设计模式。模仿只是表面,理解背后的设计哲学才是关键。

设计模式,何方神圣?

在编程的江湖里,设计模式就是解决问题的宝典,是前辈们在软件开发中留下的宝贵经验,帮我们写出可复用、灵活、高效的代码。

设计模式,三分天下

设计模式大致分为三类:

  1. 创建型模式:关注对象的诞生,如何优雅地创建和管理对象。
  2. 结构型模式:关注类和对象的“排列组合”,化简为繁,构建复杂系统。
  3. 行为型模式:关注对象之间的“互动”,定义它们如何协同工作。

“唉,又来这些概念,头都大了!”

行了行了,不卖关子了,咱们直接进入正题:简单工厂模式

第一幕:美食街的邂逅

晚上11点,你终于结束了一天的工作,疲惫地走在回家的路上。经过一条热闹的美食街,空气中弥漫着各种美食的香味,让你不由自主地停下了脚步。

你心想:“万事皆空,唯美食不可辜负,今天一定要好好犒劳自己!”但打开微信钱包一看,发现余额只剩下5块。你叹了口气,只能找个小吃摊随便吃点。

你走向最近的一个摊位,对老板说:“老板,来份煎饼果子!”

老板热情地回应:“好嘞,加不加鸡蛋?”

你摆了摆手,老板见状,便开始熟练地制作起来。

用代码表示

class Pancake {
public:
    void serve() {
        std::cout << "你的煎饼果子好了!" << std::endl;
    }
};

int main() {
    Pancake p;
    p.serve(); // 顾客:老板,来份煎饼果子!
    return 0;
}

第二幕:美食街的新品

几周后,你再次来到美食街,老板热情地向你推荐:“我们最近新增了鸡蛋灌饼,要不要尝尝?”你心想,既然来了,不妨试试新口味。

你对老板说:“老板,那就来份鸡蛋灌饼吧!”

老板手脚麻利,很快为你准备好了热腾腾的鸡蛋灌饼。

用代码表示

// ...之前的煎饼果子的代码

class EggPancake {
public:
    void serve() {
        std::cout << "热腾腾的鸡蛋灌饼好了!" << std::endl;
    }
};

int main() {
	// ...之前的煎饼果子的代码
    
    EggPancake ep;
    ep.serve(); // 顾客:老板,来份鸡蛋灌饼吧!
    return 0;
}

第三幕:美食街的繁荣

随着时间的流逝,美食街越来越繁荣,小吃摊也增加了更多的小吃品种,如手抓饼和肉夹馍。每次光顾,你都能尝试不同的美食。

用代码表示

// ...之前的煎饼果子和鸡蛋灌饼的代码
class HandPies {
public:
    void serve() {
        std::cout << "香脆的手抓饼好了!" << std::endl;
    }
};

class RouJiaMo {
public:
    void serve() {
        std::cout << "美味的肉夹馍好了!" << std::endl;
    }
};

int main() {
    // ...之前的煎饼果子和鸡蛋灌饼的代码

    HandPies hp;
    hp.serve(); // 顾客:老板,来份手抓饼!

    RouJiaMo rjm;
    rjm.serve(); // 顾客:老板,来个肉夹馍!
    return 0;
}

第四幕:简单工厂的引入

你注意到,随着小吃种类的增加,老板开始使用一张菜单,上面列出了所有可以提供的小吃。每次你只需要告诉老板你想要什么,老板就会从菜单上找到对应的小吃,然后为你准备。

你突然灵光一闪,这不正是编程中的简单工厂模式吗?通过一个统一的接口来创建不同的对象。

引入简单工厂模式

#include <memory>
#include <string>
#include <iostream>

class Snack {
public:
    virtual void serve() = 0;
    virtual ~Snack() {}
};

class Pancake : public Snack {
public:
    void serve() override {
        std::cout << "你的煎饼果子好了!" << std::endl;
    }
};

class EggPancake : public Snack {
public:
    void serve() override {
        std::cout << "热腾腾的鸡蛋灌饼好了!" << std::endl;
    }
};

// ...其他小吃类

class SnackFactory {
public:
    static std::unique_ptr<Snack> createSnack(const std::string& type) {
        if (type == "PANCAKE") {
            return std::make_unique<Pancake>();
        }
        // ...根据类型创建其他小吃
        return nullptr;
    }
};

int main() {
    auto snack = SnackFactory::createSnack("PANCAKE");
    snack->serve(); // 顾客:老板,来份煎饼果子!

    // ...根据顾客的选择,创建其他小吃

    return 0;
}

采用简单工厂模式,美食街的老板就能轻松满足顾客的各种小吃需求,顾客点餐也变得更快捷。

这个模式的妙处在于,它把创建小吃对象的过程从原来的地方挪到了一个专门的“工厂”里。一开始,你可能觉得这个改变没啥大不了的,特别是当你的程序还很简单,只有几个类的时候。但是,随着你的程序越来越庞大和复杂,这个模式的好处就会慢慢显现出来。

  • 简化代码:你不用再代码的各个角落重复写创建对象的代码了。
  • 易于管理:所有的创建逻辑都集中在工厂类里,改起来简单多了。
  • 扩展方便:想加个新小吃?在工厂类里添几行代码就行,不用满世界找代码改。
  • 减少依赖:你的代码块之间互相依赖少了,更像是独立的模块。

值得注意的是,尽管简单工厂模式没有被列入GoF的23种经典设计模式,但它在软件开发实践中仍然非常有用,特别是对于新手来说,它是学习面向对象设计原则和设计模式的一个很好的起点。

以上就是简单工厂模式的全部内容了,后面我会接着介绍GoF的23种经典设计模式,敬请期待!

📢你的每一次👍点赞 ⭐收藏 📝评论,都是我更新的动力,如有错误请留言指正,非常感谢!

posted @ 2024-05-13 13:53  知微之见  阅读(11)  评论(0编辑  收藏  举报