设计模式之工厂模式

本文转载自微信公众号「程序喵大人」,作者程序喵大人 。转载本文请联系程序喵大人公众号。

创新互联专业为企业提供巴中网站建设、巴中做网站、巴中网站设计、巴中网站制作等企业网站建设、网页设计与制作、巴中企业网站模板建站服务,十年巴中做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

01 简单工厂方法

简单工厂方法可能是最常见的工厂类创建型模式了,其中有几个角色,一个是抽象产品角色,一个是具体产品角色,多个具体产品都可以。抽象成同一个抽象产品。拿操作系统举例,操作系统作为一个抽象产品,它有几种具体产品角色,有Windows操作系统,有Android操作系统,有iOS操作系统。有一个操作系统的工厂,工厂可以根据不同的需求生产出不同内核的操作系统,这个操作系统的工厂就是最后一个角色:工厂角色。

 
 
 
  1. #include  
  2.  
  3. enum class BallEnum { BasketBall = 1, SocketBall = 2 }; 
  4.  
  5. class Ball { 
  6. public: 
  7.    Ball() {} 
  8.    virtual ~Ball() {} 
  9.  
  10. virtual void Play() {} 
  11. }; 
  12.  
  13. class BasketBall : public Ball { 
  14. public: 
  15.     void Play() override { std::cout << "play basketball \n"; } 
  16. }; 
  17.  
  18. class SocketBall : public Ball { 
  19. public: 
  20.   void Play() override { std::cout << "play socketball \n"; } 
  21. }; 
  22.  
  23. class SimpleFactory { 
  24. public: 
  25.   static Ball* CreateBall(BallEnum type); 
  26. }; 
  27.  
  28. Ball* SimpleFactory::CreateBall(BallEnum type) { 
  29.   switch (type) { 
  30.     case BallEnum::BasketBall: 
  31.       return new BasketBall(); 
  32.     case BallEnum::SocketBall: 
  33.       return new SocketBall(); 
  34.   } 
  35.   return nullptr; 
  36.  
  37. int main() { 
  38.    Ball* basket = SimpleFactory::CreateBall(BallEnum::BasketBall); 
  39.    basket->Play(); 
  40.    Ball* socket = SimpleFactory::CreateBall(BallEnum::SocketBall); 
  41.    socket->Play(); 
  42.    return 0; 

在简单工厂方法中,有一个专门的工厂类,根据不同的参数返回不同具体产品类的实例,这些具体产品可以抽象出同一个抽象产品,即有一个共同的父类。 通过上述代码您可能也看到了简单工厂方法的优点,实现了对象的创建和使用逻辑分离,只需要传入不同参数,就可以获得特定具体类的实例。但简单工厂方法也有些缺点,当增加了新的产品,就需要修改工厂类的创建逻辑,如果产品类型较多,就可能造成工厂类逻辑过于复杂,不利于系统的维护,适用于具体产品类型比较少并且以后基本不会新加类型的场景,这样工厂类业务逻辑不会太过复杂。

02 工厂方法模式

为了解决上面简单工厂方法模式的缺点,进一步抽象出了工厂方法模式,工厂类不再负责所有产品的构建,每一个具体产品都有一个对应的工厂,这样在新加产品时就不会改动已有工厂类的创建逻辑。这些工厂也会抽象出一个抽象工厂。可以理解为有四种角色,抽象产品,具体产品,抽象工厂,具体工厂,其实就是把简单工厂模式中的工厂类做进一步抽象,看代码吧:

 
 
 
  1. #include  
  2.  
  3. enum class BallEnum { BasketBall = 1, SocketBall = 2 }; 
  4.  
  5. class Ball { 
  6.   public: 
  7.    Ball() {} 
  8.    virtual ~Ball() {} 
  9.  
  10.    virtual void Play() {} 
  11. }; 
  12.  
  13. class BasketBall : public Ball { 
  14.   public: 
  15.    void Play() override { std::cout << "play basketball \n"; } 
  16. }; 
  17.  
  18. class SocketBall : public Ball { 
  19.   public: 
  20.    void Play() override { std::cout << "play socketball \n"; } 
  21. }; 
  22.  
  23. class FactoryBase { 
  24.   public: 
  25.    virtual ~FactoryBase() {} 
  26.    virtual Ball* CreateBall() = 0; 
  27. }; 
  28.  
  29. class BasketBallFactory : public FactoryBase { 
  30.   public: 
  31.    Ball* CreateBall() override { return new BasketBall(); } 
  32. }; 
  33.  
  34. class SocketBallFactory : public FactoryBase { 
  35.   public: 
  36.    Ball* CreateBall() override { return new SocketBall(); } 
  37. }; 
  38.  
  39. int main() { 
  40.    FactoryBase* factory; 
  41.    BallEnum ball_type = BallEnum::SocketBall; 
  42.    switch (ball_type) { 
  43.        case BallEnum::BasketBall: 
  44.            factory = new BasketBallFactory(); 
  45.            break; 
  46.        case BallEnum::SocketBall: 
  47.            factory = new SocketBallFactory(); 
  48.            break; 
  49.   } 
  50.    Ball* ball = factory->CreateBall(); 
  51.    ball->Play(); 
  52.    return 0; 

工厂模式提高了系统的可扩展性,完全符合开闭原则,当新加具体产品时,完全不会对已有系统有任何修改。当不知道以后会有多少具体产品时可以考虑使用工厂模式,因为不会降低现有系统的稳定性。但是它也有缺点,每当新加一个产品时,不仅需要新加一个对应的产品类,同时还需要新加一个此产品对应的工厂,系统的复杂度比较高。怎么解决呢,可以再抽象一下:

03 抽象工厂模式

在工厂方法中,每一个抽象产品都会有一个抽象工厂,这样新增一个产品时都会新增两个类,一个是具体产品类,一个是具体工厂类,我们可以考虑多个抽象产品对应一个抽象工厂,这样可以有效减少具体工厂类的个数,见如下代码:

 
 
 
  1. #include  
  2.  
  3. enum class BallEnum { BasketBall = 1, SocketBall = 2 }; 
  4.  
  5. class Ball { 
  6.   public: 
  7.    Ball() {} 
  8.    virtual ~Ball() {} 
  9.  
  10.    virtual void Play() {} 
  11. }; 
  12.  
  13. class BasketBall : public Ball { 
  14.   public: 
  15.    void Play() override { std::cout << "play basketball \n"; } 
  16. }; 
  17.  
  18. class SocketBall : public Ball { 
  19.   public: 
  20.    void Play() override { std::cout << "play socketball \n"; } 
  21. }; 
  22.  
  23. class Player { 
  24.   public: 
  25.    Player() {} 
  26.    virtual ~Player() {} 
  27.    virtual void Name() {} 
  28. }; 
  29.  
  30. class BasketBallPlayer : public Player { 
  31.   public: 
  32.    void Name() override { std::cout << "BasketBall player \n"; } 
  33. }; 
  34.  
  35. class SocketBallPlayer : public Player { 
  36.   public: 
  37.    void Name() override { std::cout << "SocketBall player \n"; } 
  38. }; 
  39.  
  40. class FactoryBase { 
  41.   public: 
  42.    virtual ~FactoryBase() {} 
  43.    virtual Ball* CreateBall() = 0; 
  44.    virtual Player* CreatePlayer() = 0; 
  45. }; 
  46.  
  47. class BasketBallFactory : public FactoryBase { 
  48.   public: 
  49.    Ball* CreateBall() override { return new BasketBall(); } 
  50.    Player* CreatePlayer() override { return new BasketBallPlayer(); } 
  51. }; 
  52.  
  53. class SocketBallFactory : public FactoryBase { 
  54.   public: 
  55.    Ball* CreateBall() override { return new SocketBall(); } 
  56.    Player* CreatePlayer() override { return new SocketBallPlayer(); } 
  57. }; 
  58.  
  59. int main() { 
  60.    FactoryBase* factory; 
  61.    BallEnum ball_type = BallEnum::SocketBall; 
  62.    switch (ball_type) { 
  63.        case BallEnum::BasketBall: 
  64.            factory = new BasketBallFactory(); 
  65.            break; 
  66.        case BallEnum::SocketBall: 
  67.            factory = new SocketBallFactory(); 
  68.            break; 
  69.   } 
  70.    Ball* ball = factory->CreateBall(); 
  71.    Player* player = factory->CreatePlayer(); 
  72.    ball->Play(); 
  73.    player->Name(); 
  74.    return 0; 

总结

系统的复杂度不会被消除,只能被转移。系统总会有稳定部分和不稳定部分,只是我们要合理选择好边界,认真思考,考虑好将哪部分打造成稳定部分,哪部分打造成不稳定部分。简单工厂方法模式中if-else的逻辑在工厂类里,如果这里在新增一个产品时有bug可能导致所有产品都创建失败,这里是不稳定部分,所以有了工厂方法模式,将工厂类内部打造成稳定部分,将不稳定的逻辑转移到外面。

网页标题:设计模式之工厂模式
网站URL:http://www.gawzjz.com/qtweb2/news13/9063.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联