通用工厂类Factory(C++实现)

本文探讨了C++中工厂模式的应用,强调了在增加新产品类时需要修改抽象工厂接口及其影响,如接口扩大、工厂类数量增加等。此外,还提到了未注册或拼写错误的产品名在运行时可能导致的错误,以及需要在运行期注册类和回调函数到工厂的问题,指出这些问题可能带来的效率降低和管理复杂性。
摘要由CSDN通过智能技术生成
灵光一闪:
        抽象工厂模式经常被使用,那么同时也会多次写相同或类似的代码。能不能设计一个通用的工厂类,以避免重复设计工厂类呢?


        先回忆一下基础的工厂类设计。
 	class Button
        {
        };

        class LinuxButton : public Button
        {
        };

        class WindowsButton: public Button
        {
        };

        class AbstractFactory
        {
         public:
            Button* create Button() = 0;
        };

        class LinuxConcreteFactory : public AbstractFactory
        {
         public:
            Button* createButton()
            {
                return new LinuxButton ;
            }
        };
        
        class WindowsConcreteFactory : public AbstractFactory
        {
        pulbic:
            Base *createBase()
            {
                return new WindowsButton;
            }
        };


         以上是一个基本的抽象工厂类。这套代码会根据不同的操作实现不同的控件,比如运行在linux下,那么会要产生一个Linux格式的Button,运行在Windows下,那么会产生Windows的Button。很多用过工厂类的猿们应该都有写过这样的工厂。但是这样的工厂有很大的问题:
  1. 有新产品类时,要修改AbstractFactory的接口,同时要改变所有具体工厂去实现新的创建对象函数。比如,现在要加一个Label的控件,那么会有Label、LinuxLabel和WindowsLabel类。这时就要去修改AbstractFactory的接口,然后所有实现类都要去实现新的函数。
  2. 要记住每个类创建对象的对应函数,当然,名字取得得当,这不是问题,就像上面的例子一样,对于类Button,创建一个createButton的函数。
  3. 当要使用这个工厂创建对象的类非常多时,这时工厂的接口就非常大。
  4. 当具体工厂的个数比较多时,这样实现具体工厂就更加麻烦。比如,这时要加上Mac系统的控件,此时就得去新建一个MacConcreteFactory的类,并去继承AbstractFactory类,然后实现所以函数。

         那么有没有比较简便点的方法呢?

=============================================================================
         下面给出一个《C++ API设计》这本书的一个工厂类的设计。
        Button* createLinuxButton()
        {
            return new LinuxButton;
        }

        Button *createWindowsButton()
        {
            return new WindowsButton;
        }

        class ButtonFactoryEx
        {
        public:
                void registerClass(const string &name, Button* (*callback)())
                {
                    cm[name] = callback;
                }

                Button* create(const string &name)
                {
                    CreateMap::iterator it = cm.find(name);
                    if (it != cm.end())
                    {
                        return (*(it->second))();
                    }
                    else
                    {
                        return NULL;
                    }
                }
                // ...省略一些其他不用介绍的函数,可以参考《C++ API设计》
        private:
                typedef Button* (*CreateCallback)();
                typedef map<string, CreateCallback> CreateMaps;
                CreateMaps cm;
        };


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值