代码之家  ›  专栏  ›  技术社区  ›  Robben_Ford_Fan_boy

可选成员对象

  •  2
  • Robben_Ford_Fan_boy  · 技术社区  · 16 年前

    好的,所以在系统的主类周围有很多方法。因此,您可以通过创建一个新类并将move方法执行到一个新类中来做正确的事情和重构。新的阶级有一个单一的责任,一切又回到了正确的世界:

    class Feature
    {
    public:
        Feature(){};
    
        void doSomething();
        void doSomething1();
        void doSomething2();   
    };
    

      Feature _feature;
    

    你可以在主课上叫它。现在,如果您多次这样做,您的主类中将有许多成员对象。

    现在,这些特性可能需要或不需要基于配置,所以在某种程度上,拥有所有这些可能需要或不需要的对象是非常昂贵的。

    有人能提出一个改进的方法吗?


    定义功能接口的抽象类:

    class IFeature
    {
    public:
        virtual void doSomething()=0;
        virtual void doSomething1()=0;
        virtual void doSomething2()=0;
    
        virtual ~IFeature(){}
    };
    

    class RealFeature:public IFeature
    {
    public:
        RealFeature(){};
    
        void doSomething(){std::cout<<"RealFeature doSomething()"<<std::endl;}
        void doSomething1(){std::cout<<"RealFeature doSomething()"<<std::endl;}
        void doSomething2(){std::cout<<"RealFeature doSomething()"<<std::endl;}
    }; 
    

    class NullFeature:public IFeature
    {
    public:
        NullFeature(){};
    
        void doSomething(){std::cout<<"NULL doSomething()"<<std::endl;};
        void doSomething1(){std::cout<<"NULL doSomething1()"<<std::endl;};
        void doSomething2(){std::cout<<"NULL doSomething2()"<<std::endl;};
    
    
    };
    

    然后我定义了一个代理类,它将根据配置委托给实对象或空对象:

    class Feature:public IFeature
    {
    public:
        Feature();
        ~Feature();
    
        void doSomething();
        void doSomething1();
        void doSomething2();
    
    private:
        std::auto_ptr<IFeature> _feature;
    };
    

    实施:

       Feature::Feature()
        {
            std::cout<<"Feature() CTOR"<<std::endl;
            if(configuration::isEnabled() )
            {
                _feature = auto_ptr<IFeature>( new RealFeature() );
            }
            else
            {
                _feature = auto_ptr<IFeature>( new NullFeature() );
            }
        }
    
    
        void Feature::doSomething()
        {
            _feature->doSomething();
        }
    
        //And so one for each of the implementation methods
    

    Feature _feature;
    
    _feature.doSomething();
    
    4 回复  |  直到 16 年前
        1
  •  3
  •   munificent    16 年前

    如果缺少某个功能,正确的做法是忽略该事实而不执行任何操作,则可以使用 Null Object pattern :

    class MainThing {
        IFeature _feature;
    
        void DoStuff() {
            _feature.Method1();
            _feature.Method2();
    }
    
    interface IFeature {
        void Method1();
        void Method2();
    }
    
    class SomeFeature { /* ... */ }
    
    class NullFeature {
        void Method1() { /* do nothing */ }
        void Method2() { /* do nothing */ }
    }
    

    MainThing ,如果可选功能不存在,则将其引用到 NullFeature 而不是实际的 null 主要 _feature 不是吗 无效的 .

        2
  •  3
  •   Owen S.    16 年前

    class Foo {
    private:
        Feature* _feature;
    public:
        Foo() : _feature(NULL) {}
        Feature* getFeature() {
            if (! _feature) {
                _feature = new Feature();
            }
            return _feature;
        }
    };
    

    现在你可以把它包起来了 Feature* 如果您需要有关内存管理的帮助,请使用智能指针。但关键不在于内存管理,而是懒惰的创造。这样做的好处不是选择性地配置你想在启动时创建的东西,而是你不需要配置——你只需按需付费。有时候这就是你所需要的。

    请注意,这种特定实现的一个缺点是,创建现在发生在客户机第一次调用他们认为只是getter的对象时。如果创建对象非常耗时,那么这可能会对您的客户机造成一些冲击,甚至是一个问题。它还使getter变为非常量,这也可能是一个问题。最后,它假设您拥有按需创建对象所需的一切,这对于难以构造的对象来说可能是个问题。

        3
  •  1
  •   M. Williams    16 年前

    在你的问题描述中有一个时刻,实际上会导致失败。 “回来吧” 如果您的功能不可用,您应该在调用前检查功能的可用性!

    尝试用不同的方法设计主类。考虑将类的一些抽象描述符 FeatureMap 或者类似的东西,实际存储当前类的可用特性。

    功能图 只有这样才能调用它。如果遇到调用不支持的功能的情况,则抛出异常。

    特征查找 例行公事要快 不会影响你的表现。


    (因为我对你的问题领域没有任何想法,而且更好的解决方案总是针对特定领域的) ,但希望这能让你正确思考。

        4
  •  1
  •   utnapistim    16 年前

    具体来说,你可以:

    class FeatureImpl
    {
    public:
        void doSomething() { /*real work here*/ }
    };
    
    class Feature
    {
        class FeatureImpl * _impl;
    public:
        Feature() : _impl(0) {}
        void doSomething()
        {
            if(_impl)
                _impl->doSomething();
            // else case ... here's your null object implementation :)
        }
        // code to (optionally) initialize the implementation left out due to laziness
    };
    

    if(_impl)