设计模式 笔记 装饰模式 Decorator

来源:互联网 发布:字符串添加到数组 编辑:程序博客网 时间:2024/06/04 23:20



//---------------------------15/04/17----------------------------



//Decorator 装饰模式----对象结构型模式

/*

    1:意图:

        动态地给一个对象添加额外的职业,就增加功能来说,Decorator模式相比生成子类更为灵活。

    2:别名:

        包装器(Wrapper)

    3:动机:

    4:适用性:

        1>在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

        2>处理那些可以撤销的职责。

        3>当不能采用生成子类的方法进行扩充时:

            1)可能有大量独立的扩展,为支持每一种组合将产生大量的子类。

            2)类定义被隐藏,或类定义不能用于生成子类。

    5:结构:

                Component:<------------------

                Operation                   |

                    |                       |

                    |                       |

            ------------------              |

            |                |              |

    ConcreteComponent:      Decorator:      |

    Operation()             component--------

                            Operation()

                            { component->Operation() }

                                |

                                |

                        --------------------

                        |                  |

                ConcreteDecoratorA: ConcreteDecoratorB:

                Operation()         Operatione()

                addedState()        {   Decorator::Operation();

                                        AddedBehavior();        }

                                    AddedBehavior()

    6:参与者:

        1>Component

            定义一个对象接口,可以给这些对象动态地添加职责。

        2>ConcreteComponent

            定义一个对象,可以给这个对象添加职责。

        3>Decorator

            维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。

        4>ConcreteDecorator

            向组件添加职责。

    7:协作:

        Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。

    8:效果:

        1>优点:

            1)比静态继承更灵活。

                Decorator模式提供了更加灵活的向对象添加职责的方式,在运行时刻添加和删除职责。

                相比于使用继承,Decorator模式可以很容易地重复添加一个特性,而重复继承很容易出错。

            2)避免在层次结构高层的类有太多特征。

                Decorator模式提供了一种即用即付的方法来添加职责。可以对一个简单的类扩展出复杂的

                功能。

        2>缺点:

            1)Decorator和它的Component不一样。

                被装饰了的组件和没装饰时是有差别的,因此,使用装饰时不应该依赖对象标识。

                装饰后,在别的对象看来,就是Decorator类了,而不是ConcreteCompnent类了

            2)有许多小对象。

                采用Decorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互

                连接的方式上有所不同,而不是它们的类或是他们的属性值有所不同。所以这些系统很难学习和排错。

    9:实现:

        1>接口的一致性:

            装饰对象的接口必须与它所装饰的Component的接口是一致的,因此所有的ConcreteDecorator类必须

            有一个公共的父类。

        2>省略抽象的Decorator类:

            当你仅需要添加一个职责时,没有必要定义抽象的Decorator类。

        3>保持Component类的简单性:

            为了接口的一致性,组件和装饰都必须继承自Component类,所以保持这个类的简单性很重要。

            也就是把这个类设计目的集中于接口设计,而不是存储数据。

        4>改变对象外壳与改变对象内核:

            可以把Decorator类当作是一个对象的外壳,添加Decorator类可以改变一个对象的行为,但是当

            Component类很庞大时,添加一个Decorator类代价就显得很大。所以可以选择使用另外一种模式:

            Strategy模式,组件可以将一些行为转发给一个独立的策略对象,通过改变策略对象,就可以达到

            改变或扩充组件的功能。

    10:代码示例:                                                                            */


//Component类,提供了接口

class VisualComponent

{

public:

    VisualComponent();

   virtualvoid Draw();

   virtualvoid Resize();

    ...

};



//abstract Decorator

class Decorator :public VisualComponent

{

public:

    Decorator(VisualComponent*);

    

   virtualvoid Draw();

   virtualvoid Resize();

    ...

private:

    VisualComponent* _component;

};


void Decorator::Draw()

{

    _component->Draw();

}


void Decorator::Resize()

{

    _component->Resize();

}


//ConcreteDecorator 在自己的Draw()中添加了要添加的职责--绘制边框

class BorderDecorator :public Decorator

{

public:

    BorderDecorator(VisualComponent*,int borderWidth);

    

   virtualvoid Draw();

private:

   void DrawBorder(int);

    

private:

   int _width;

};


void BorderDecorator::Draw()

{

    Decorator::Draw();

    DrawBorder(_width);

}


//这里的SetContents以一个Component指针为参数,来进行一些操作,

//通过装饰就可以传入一个装饰过的类

void Window::SetContents(VisualComponent* contents)

{

    ...

}


Window* window =new Window;

//未经装饰的类,TextView是继承自Component类的ConcreteComponent

TextView* textView =new TextView;


//它可以被这样传入

window->SetContents(textView);


//也可以通过装饰来传入,这样装饰就增加了起码两个Component大小的内存了,所以

//如果Compnent如果很庞大的话,使用代价会很高。

window->SetContents(new BorderDecorator(new ScrollDecorator(textView),1));


//再考虑一个问题,如果深度很深的话,实现起来效率也会下降。

//何谓深度,就是装饰了很多很多次,这里的调用其实就是通过指针不断访问下一个对象调用Draw(),就和链表一样,

//如果深度很深,那么就像遍历链表一样。

//这时可以考虑实现中最后一点说的,使用strategy模式。



0 0
原创粉丝点击