装饰模式笔记

菜鸟教程连接https://www.runoob.com/design-pattern/decorator-pattern.html

UML类图入下 :

在Java的IO流的类图

解决的问题 :

  • 想给一个类扩展功能,但是不想继承

  • 可以动态扩展功能,撤消功能(不知到体现在哪里)

  • 需要给已有的类扩展功能,并且要添加新字段时可用

  • 可以改变装饰顺序,参考java的io流

    InputStream input = null;
    input = new BufferedInputStream(new GZIPInputStream(new DataInputStream(new FileInputStream("file.txt"))));
    
    input = new GZIPInputStream(new DataInputStream(new BufferedInputStream(new FileInputStream("file.txt"))));
    

注意点:

  • 装饰器需要继承自被装饰者

概括:

  • 装饰器需要继承自被装饰者
  • 装饰器有一个被装饰者成员变量,重写接口时可以调用该成员变量的函数

用到的地方:

  • JDK的IO流

实现:

现在我们要做个画图工具,如上面的类图,目前我们已有一个Shape图形接口

两个具体图形类Rect和Circle,现在我们想要添加一个画红色图形的功能,但是又不想动那两个图形类(不想继承),于是可以添加一个装饰器类,该装饰器拥有图形的所有功能draw(),并且还有扩展的功能setRedBorde()可以画出红色图形,具体做法就是:装饰器实现图形接口,有一个图形成员变量shape,通过构造函数设置shape,实现的接口可以直接调用shape->draw(),于是就可以在装饰器里添加新的功能setRedBorde()了。

代码如下:

原来已经有的图形接口Shape和两个具体实现类RectCircle

// 原来已有的图形接口 
class Shape : public MajiaoObject { 
    public :  
        Shape() {  } 
        ~Shape() {  } 

        // 图形接口类的绘制方法
        virtual void draw() { }
}; 

// 具体长方形类
class Rect : public Shape { 
    public :  
    	int w, h;
        Rect() {  } 
        ~Rect() {  } 
        virtual void draw() { cout << "矩形绘制算法" << endl; }
}; 

// 具体圆形类
class Circle : public Shape { 
    public :  
    	int r, d;
        Circle() {  } 
        ~Circle() {  } 
        virtual void draw() { cout << "Bresenham画圆算法" << endl; }
}; 

现在我们要扩展新功能画红色图形,不想去挨个继承RectCircle

于是有了装饰器类

// 装饰器接口,必须继承被装饰者的接口 
class ShapeDecorator : public Shape { 
    public :  
        // 被装饰的对象
        Shape* shape;
    	// 使用构造设置成员变量
        ShapeDecorator(Shape* shape) { this->shape = shape; } 
        ~ShapeDecorator() {  } 
}; 

// 实现一个具体的装饰器【红色绘制图形装饰器】 
class RedShapeDecorator : public ShapeDecorator { 
    public :  
        // 调用父类的构造
        RedShapeDecorator(Shape* shape) : ShapeDecorator(shape) {  } 
        ~RedShapeDecorator() {  } 

        virtual void draw() {
            // 调用被装饰者的draw
            if (shape) { 
                setRedBorde(); // 设置画笔颜色
                shape->draw();
            }
        }

        // 给原来的图形类添加一个设置边框为红色的功能,但是不需要继承原来的类
        virtual void setRedBorde() { cout << "画笔设置成红色了" << endl; }
}; 

在调用方就可以嵌套new(装饰对象)

  • 类似于java的io流
// 可以实现像 java IO流的嵌套 new 
Shape *mainRect = new BackgroudShapeDecorator(new RedShapeDecorator(new Rect())), // 先装饰边框颜色,再装饰背景色
      *mainCircle = new RedShapeDecorator(new BackgroudShapeDecorator(new Circle())); // 先装饰背景色,再装饰边框颜色
mainRect->draw();
mainRect->draw();
posted @ 2021-06-19 13:50  马角的逆袭  阅读(31)  评论(0编辑  收藏  举报