C语言实现OOP 版本2

写版本2的原因,还是发现在不同的具体图形模块里发现了重复的release代码,这是坏味道,所以还是决定消除这些重复代码,DRY


shape.h

#ifndef SHAPE_H

#define SHAPE_H



typedef struct shape_t 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Shape;



void release(void *shape);



#endif

shape.c

#include <stdlib.h>

#include "shape.h"



void release(void *shape)

{

    free(((Shape*)shape)->shapeData);

    free(shape);

}

circle.h

#ifndef CIRCLE_H

#define CIRCLE_H



typedef struct

{

    double r;

}CircleData;



typedef struct 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Circle;



Circle *makeCircle(double r);



#endif

circle.c

#include <assert.h>

#include <stdlib.h>

#include <stdio.h>

#include "shape.h"

#include "circle.h"



const double PI = 3.14159;



static void area(void *shape)

{

    Circle *_circle = (Circle *)shape;

    CircleData* data = (CircleData*)_circle->shapeData;

    printf("the circle area is %f \n", data->r * data->r * PI);

}



/*

static void release(void *shape)

{

    Circle *_circle = (Circle *)shape;

    CircleData* data = (CircleData*)_circle->shapeData;

    free(data);

    free(_circle);

}

*/



Circle *makeCircle(double r)

{

    CircleData* circleData = (CircleData*)malloc(sizeof(CircleData));

    Circle* circle = (Circle*)malloc(sizeof(Circle));

    assert(circleData != NULL);

    assert(circle != NULL);

    assert(r > 0);



    

    circleData->r = r;

    circle->shapeData = circleData;

    circle->area = &area;

    circle->release = &release;



    return circle;

}

square.h

#ifndef SQUARE_H

#define SQUARE_H



typedef struct

{

    double x;

    double y;

}SquareData;



typedef struct 

{

    void *shapeData;

    void (*area)(void *);

    void (*release)(void *);

}Square;



Square *makeSquare(double x, double y);



#endif

square.c

#include <assert.h>

#include <stdlib.h>

#include <stdio.h>

#include "shape.h"

#include "square.h"



static void area(void *shape)

{

    Square *square = (Square *)shape;

    SquareData* data = (SquareData*)square->shapeData;

    printf("the square area is %f \n", data->x * data->y);

}



/*

static void release(void *shape)

{

    Square *square = (Square *)shape;

    SquareData* data = (SquareData*)square->shapeData;

    free(data);

    free(square);

}

*/



Square *makeSquare(double x, double y)

{

    SquareData* squareData = (SquareData*)malloc(sizeof(SquareData));

    Square* square = (Square*)malloc(sizeof(Square));

    assert(squareData != NULL);

    assert(square != NULL);

    assert(x > 0 && y > 0);



    squareData->x = x;

    squareData->y = y;

    square->shapeData = squareData;

    square->area = &area;

    square->release = &release;



    return square;

}

main.c 发现没有,尽管内部进行了调整,这些的代码丝毫没变!重构就应该这样,内部的调整不太涉及到client代码,除非真的决定修改接口,修改接口内部应该优先于调整接口

#include <stdio.h>

#include "shape.h"

#include "circle.h"

#include "square.h"



void printShapeArea(Shape **shape,int length)

{

    int i=0;

    for(i=0;i<length;i++)

    {

        shape[i]->area(shape[i]);

        shape[i]->release(shape[i]);

    }

}



int main()

{

    Shape *p[3] = {(Shape*)makeCircle(3.2),(Shape*)makeCircle(3.2),(Shape*)makeSquare(3.1,4)};

    printShapeArea(p,3);

    return 0;

}

 

 

 

 

 

 

你可能感兴趣的:(oop)