zoukankan      html  css  js  c++  java
  • 原型模式笔记

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

    《大话设计模式》的UML类图入下 :

    菜鸟教程的UML类图如下:

    解决的问题 :

    • 在运行期间建立和删除原型
    • 逃避构造函数的约束
    1. 接口类ICloneable.hpp里要有clone()函数

      #ifndef _ICLONEABLE_H 
      #define _ICLONEABLE_H 
      
      #include <stdlib.h> 
      #include "MajiaoObject.hpp" 
       
      class ICloneable : public MajiaoObject { 
          public :  
              ICloneable() {  } 
              ~ICloneable() {  } 
              
              // 纯虚函数
              virtual ICloneable* clone() = 0;
      		
          	// 一个简单拷贝,浅拷贝
              virtual ICloneable* clone(int objSize) {
                  char* objClone = (char*) malloc(objSize);
                  memcpy(objClone, this, objSize);
                  return (ICloneable*) objClone;
              }
      }; 
      #endif	// _ICLONEABLE_H
      
    2. 图形类Shape要实现ICloneable的函数

      #ifndef _SHAPE_H 
      #define _SHAPE_H 
      #include "ICloneable.hpp" 
       
      class Shape : public ICloneable { 
          public :  
              int color;
              int w, h;
              Shape() {  } 
              ~Shape() {  } 
      		
          	// 重写父类的clone函数
              virtual ICloneable* clone() override {
                  Shape* objClone = new Shape();
                  *objClone = *this;
                  return objClone;
              }
      
              virtual double calcArea() {
                  return w * h;
              }
      }; 
      #endif	// _SHAPE_H
      
    3. 图形的子类CircleRectOval都要重写父类的clone()

      • 没有新的成员变量,可以用父类的clone()

        #ifndef _RECT_H 
        #define _RECT_H 
         
        #include "Shape.hpp" 
        
        // Rect没有重写clone,因为没有新的成员变量,可以直接用父类的clone
        class Rect : public Shape { 
            public :  
                Rect() {  } 
                ~Rect() {  } 
        }; 
        #endif	// _RECT_H
        
      • 有新的成员变量,需要重写clone()

        #ifndef _OVAL_H 
        #define _OVAL_H 
        
        #include <math.h> 
        #include "Shape.hpp" 
         
        // 椭圆
        class Oval : public Shape { 
            public :  
        
                double a, b, c;
        
                // 焦点,在x轴上,在y轴上
                enum FOCUS { FOCUS_X, FOCUS_Y };
        
                Oval() {  } 
                ~Oval() {  } 
        		
            	// 有新成员a,b,c,要重写拷贝
                virtual ICloneable* clone() override {
                    // Oval* objClone = new Oval();
                    // *objClone = *this;
                    // return (ICloneable*)(objClone);
                    return ICloneable::clone(sizeof(Oval));
                }
        
                virtual double calcArea() {
                    // S = PI * A * B
                    return acos(-1) * a * b;
                }
        }; 
        #endif	// _CIRCLE_H
        
      • 当有成员变量是指针时,要深拷贝,书上重载了构造函数,在构造的时候clone

        #ifndef _CIRCLE_H 
        #define _CIRCLE_H 
        
        #include "Oval.hpp" 
        
        // 圆形是特殊的椭圆,使用装饰器(这里其实应该继承,用装饰器只是为了演示“有指针变量”的clone)
        class Circle : public Oval { 
            public :  
                Oval* oval;
                Circle() { }
        
                // 书上说,在构造里添加一个对 成员指针的clone即可
                Circle(Oval* oval) { 
                    this->oval = (Oval*) oval->clone();
                } 
                ~Circle() {  } 
        
                virtual ICloneable* clone() {
                    // 调用构造去克隆成员指针
                    Circle* objClone = new Circle(this->oval);
                    objClone->h = this->h;
                    objClone->w = this->w;
                    objClone->color = this->color;
                    return objClone;
                }
        }; 
        #endif	// _CIRCLE_H
        
    4. 在调用方就直接xxx->clone()即可

      signed main() {
          Shape* shape = new Rect(),
                 *oval = new Oval();
          Circle *circle = new Circle(new Oval()); 
          circle->oval->a = 999;
          shape->color = 0xff;
          circle->color = 0x77;
          // 两种clone方式
          ICloneable *rectColone = shape->clone(), 
          			//成员变量浅拷贝,成员变量是指针类型时要小心
                     *rectClone2 = shape->
                         ICloneable::clone(int(sizeof(Shape))), 
                     *overClone = oval->clone(),
                     // "成员变量是指针" 的深拷贝clone方式
                     *circleClone = circle->clone();
      
          cout << shape->color << endl;
          cout << ((Shape*)rectColone)->color << endl;
          cout << ((Shape*)rectClone2)->color << endl;
          cout << ((Shape*)circleClone)->color << "  " << ((Circle*)circleClone)->oval->a << endl;
          return 0;
      }
      
      
    5. TODO,使用宏来实现clone()函数

  • 相关阅读:
    CSS切割
    一台电脑 多个 tomcat
    CGI
    电源关系
    Monkey Test 命令使用
    html ul
    java 反射
    RTMP
    动态库
    flash 大文件上传
  • 原文地址:https://www.cnblogs.com/majiao61/p/14966159.html
Copyright © 2011-2022 走看看