【原型设计模式详解】C/Java/JS/Go/Python/TS不同语言实现-今日视点

博客园   2023-04-24 11:07:49


(资料图)

简介

原型模式(Prototype Pattern)是一种创建型设计模式,使你能够复制已有对象,而无需使代码依赖它们所属的类,同时又能保证性能。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。

如果你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类,可以使用原型模式。

作用利用已有的一个原型对象,快速地生成和原型对象一样的实例。跳过构造函数的约束,便于提升性能。实现步骤创建原型接口,并声明克隆方法。使用new运算符调用原型版本的构造函数。将子类构造函数的直接调用,替换为对原型工厂方法的调用。UMLJava代码基础原型抽象类
// Shape.java 基础抽象类public abstract class Shape implements Cloneable {  private int width;  private int height;  private String color = "";  protected String type;  public Shape() {  }  public String getType() {    return type;  }  // 抽象方法,子类覆盖  public abstract void draw();  public void setWidth(int width) {    this.width = width;  }  public int getWidth() {    return this.width;  }  public int getHeight() {    return this.height;  }  public void setHeight(int height) {    this.height = height;  }  public void setColor(String color) {    this.color = color;  }  public String getColor() {    return this.color;  }  // 克隆方法  public Object clone() {    Object clone = null;    try {      clone = super.clone();    } catch (CloneNotSupportedException e) {      e.printStackTrace();    }    return clone;  }  @Override  public String toString() {    return String.format("{width = %s, height = %s, type = %s, color = %s }",        this.width, this.height, this.type, this.color);  }}
具体原型者
// Circle.java 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。public class Circle extends Shape {  public Circle() {    super();    type = "Circle";  }  @Override  public void draw() {    System.out.println("Circle::draw() method.");  }}
// Rectangle.java 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。public class Rectangle extends Shape {  public Rectangle() {    super();    type = "Rectangle";  }  @Override  public void draw() {     System.out.println("Rectangle::draw() method.");  }}
// 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。public class Square extends Shape {  public Square() {    super();    type = "Square";  }  @Override  public void draw() {    System.out.println("Square::draw() method.");  }}
客户使用类
// Application.java 客户调用方public class Application {  public List shapes = new ArrayList();  public Application() {  }  public void addToShapes() {    Circle circle = new Circle();    circle.setWidth(10);    circle.setHeight(20);    circle.setColor("red");    shapes.add(circle);    // 添加clone    Circle anotherCircle = (Circle) circle.clone();    anotherCircle.setColor("pink");    shapes.add(anotherCircle);    // 变量 `anotherCircle(另一个圆)`与 `circle(圆)`对象的内容完全一样。    Rectangle rectangle = new Rectangle();    rectangle.setWidth(99);    rectangle.setHeight(69);    rectangle.setColor("green");    shapes.add(rectangle);    // 添加clone    shapes.add((Shape) rectangle.clone());  }  // 直接取出  public Shape getShape(Integer index) {    return this.shapes.get(index);  }  // 取出时候clone  public Shape getShapeClone(Integer index) {    Shape shape = this.shapes.get(index);    return (Shape) shape.clone();  }  public void printShapes() {    for (int i = 0; i < this.shapes.size(); i++) {      Shape shape = this.shapes.get(i);      System.out.println("shape " + i + " : " + shape.toString());    }  }}
测试调用
/**     * 原型模式主要就是复制已有的对象,而无需实例化类,从而提升实例化对象时的性能     * 其实就是复制实例的属性到新对象上,减少了执行构造的步骤     */    Application application = new Application();    application.addToShapes();    Shape shapeClone = application.getShapeClone(1);    // 更改clone    shapeClone.setColor("gray");    System.out.println("shapeClone : " + shapeClone.toString());    // 直接更改    application.getShape(3).setColor("yellow");    application.printShapes();    // /*********************** 分割线 ******************************************/    application.shapes.add(new Square());    for (Shape shape : application.shapes) {      shape.draw();      System.out.println(shape.toString());    }
C代码基础原型抽象类
// func.h 基础头文件#include #include #include #include #include typedef struct Shape shape;typedef struct Circle circle;typedef struct Rectangle rectangle;typedef struct Square square;// 定义了Shape作为基础接口,以便各形状有统一类型typedef struct Shape{    char name[50];    int width;    int height;    char color[50];    char category[50];    void (*draw)(struct Shape *shape);    struct Shape *(*clone)(struct Shape *shape);    char *(*to_string)(struct Shape *shape);    void (*set_width)(struct Shape *shape, int width);    int (*get_width)(struct Shape *shape);    void (*set_height)(struct Shape *shape, int height);    int (*get_height)(struct Shape *shape);    void (*set_color)(struct Shape *shape, char *color);    char *(*get_color)(struct Shape *shape);    void (*set_category)(struct Shape *shape, char *category);    char *(*get_category)(struct Shape *shape);} Shape;Shape *shape_constructor(char *name);typedef struct Circle{    char name[50];    int width;    int height;    char color[50];    char category[50];    void (*draw)(struct Circle *shape);    struct Circle *(*clone)(struct Circle *shape);    char *(*to_string)(struct Circle *shape);    void (*set_width)(struct Circle *shape, int width);    int (*get_width)(struct Circle *shape);    void (*set_height)(struct Circle *shape, int height);    int (*get_height)(struct Circle *shape);    void (*set_color)(struct Circle *shape, char *color);    char *(*get_color)(struct Circle *shape);    void (*set_category)(struct Circle *shape, char *category);    char *(*get_category)(struct Circle *shape);} Circle;Circle *circle_constructor(char *name);typedef struct Square{    char name[50];    int width;    int height;    char color[50];    char category[50];    void (*draw)(struct Square *shape);    struct Square *(*clone)(struct Square *shape);    char *(*to_string)(struct Square *shape);    void (*set_width)(struct Square *shape, int width);    int (*get_width)(struct Square *shape);    void (*set_height)(struct Square *shape, int height);    int (*get_height)(struct Square *shape);    void (*set_color)(struct Square *shape, char *color);    char *(*get_color)(struct Square *shape);    void (*set_category)(struct Square *shape, char *category);    char *(*get_category)(struct Square *shape);} Square;Square *square_constructor(char *name);typedef struct Rectangle{    char name[50];    int width;    int height;    char color[50];    char category[50];    void (*draw)(struct Rectangle *shape);    struct Rectangle *(*clone)(struct Rectangle *shape);    char *(*string)(struct Rectangle *shape);    void (*set_width)(struct Rectangle *shape, int width);    int *(*get_width)(struct Rectangle *shape);    void (*set_height)(struct Rectangle *shape, int height);    int *(*get_height)(struct Rectangle *shape);    void (*set_color)(struct Rectangle *shape, char *color);    char *(*get_color)(struct Rectangle *shape);    void (*set_category)(struct Rectangle *shape, char *category);    char *(*get_category)(struct Rectangle *shape);} Rectangle;Rectangle *rectangle_constructor(char *name);// 调用客户端typedef struct Application{    struct Shape **shapes;    int shapes_length;    void (*add_to_shapes)(struct Application *app);    void (*add_shape)(struct Application *app, Shape *shape);    Shape *(*get_shape)(struct Application *app, int index);    Shape **(*get_shapes)(struct Application *app);    Shape *(*get_shape_clone)(struct Application *app, int index);    void (*print_shapes)(struct Application *app);} Application;Application *application_constructor();
// shape.c 基础类,供各种具体形状复用#include "func.h"// shape基础抽象类,供子类继承覆盖// C没有抽象和继承,此处作为公共类存在void shape_draw(Shape *shape){  printf("\r\n Shape::draw()");}void shape_set_width(Shape *shape, int width){  shape->width = width;}int shape_get_width(Shape *shape){  return shape->width;}int shape_get_height(Shape *shape){  return shape->height;}void shape_set_height(Shape *shape, int height){  shape->height = height;}void shape_set_color(Shape *shape, char *color){  strncpy(shape->color, color, 50);}char *shape_get_color(Shape *shape){  return shape->color;}void shape_set_category(Shape *shape, char *category){  strncpy(shape->category, category, 50);}char *shape_get_category(Shape *shape){  return shape->category;}char *shape_to_string(Shape *shape){  static char result[1024];  sprintf(result, "[name = %s width = %d, height = %d, category = %s, color = %s]",          shape->name, shape->width, shape->height, shape->category, shape->color);  return result;}// 将指针指向同一内存的方式来实现cloneShape *shape_clone(Shape *shape){  Shape *copy = (Shape *)malloc(sizeof(Shape));  memcpy(copy, shape, sizeof(Shape));  strcat(copy->name, "(clone)");  // printf("\r\n shape_clone: %s", copy->to_string(copy));  return copy;}// 定义简单结构体,复制基本属性和draw函数Shape *shape_clone2(Shape *shape){  struct Shape copy = {      .width = shape->width,      .height = shape->height,  };  strcpy(copy.name, shape->name);  strcat(copy.name, "[clone]");  strcpy(copy.color, shape->color);  strcpy(copy.category, shape->category);  Shape *shape_copy = ©  shape_copy->draw = shape->draw;  // printf("\r\n shape_clone: %s", shape->to_string(shape_copy));  return shape_copy;}Shape *shape_constructor(char *name){  printf("\r\n shape_constructor() [构建Shape]");  Shape *shape = (Shape *)malloc(sizeof(Shape));  strncpy(shape->name, name, 50);  shape->draw = &shape_draw;  shape->clone = &shape_clone;  shape->to_string = &shape_to_string;  shape->set_width = &shape_set_width;  shape->get_width = &shape_get_width;  shape->set_height = &shape_set_height;  shape->get_height = &shape_get_height;  shape->set_color = &shape_set_color;  shape->get_color = &shape_get_color;  shape->set_category = &shape_set_category;  shape->get_category = &shape_get_category;  return shape;}
具体原型者
// circle.c 具体原型类,复用父类方法,实现自己的draw函数。#include "func.h"// 重新定义draw函数void circle_draw(Circle *shape){  printf("\r\n Circle::draw()");}Circle *circle_constructor(char *name){  printf("\r\n shape_constructor() [构建Circle]");  Shape *shape = (Shape *)shape_constructor(name);  Circle *circle = (Circle *)shape;  circle->draw = &circle_draw;  return circle;}
// rectangle.c 具体原型类,复用父类方法,实现自己的draw函数。#include "func.h"// 重新定义draw函数void rectangle_draw(Rectangle *shape){  printf("\r\n Rectangle::draw()");}Rectangle *rectangle_constructor(char *name){  printf("\r\n shape_constructor() [构建Rectangle]");  Shape *shape = (Shape *)shape_constructor(name);  Rectangle *rectangle = (Rectangle *)shape;  rectangle->draw = &rectangle_draw;  return rectangle;}
// square.c 具体原型类,复用父类方法,实现自己的draw函数。#include "func.h"// 重新定义draw函数void square_draw(Square *shape){  printf("\r\n Square::draw()");}Square *square_constructor(char *name){  printf("\r\n shape_constructor() [构建Square]");  Shape *shape = (Shape *)shape_constructor(name);  Square *square = (Square *)shape;  square->draw = &square_draw;  return square;}
客户使用类
// application.c 客户调用方#include "func.h"void app_add_to_shapes(Application *app){  Circle *circle = circle_constructor("circle");  circle->set_category(circle, "Circle");  circle->set_width(circle, 10);  circle->set_height(circle, 20);  circle->set_color(circle, "red");  app->add_shape(app, (Shape *)circle);  // 添加Clone  Circle *another_circle = circle->clone(circle);  another_circle->set_color(another_circle, "pink");  app->add_shape(app, (Shape *)another_circle);  // 变量 `another_circle(另一个圆)`与 `circle(圆)`对象的内容完全一样。  Rectangle *rectangle = rectangle_constructor("rectangle");  rectangle->set_category(rectangle, "Rectangle");  rectangle->set_width(rectangle, 99);  rectangle->set_height(rectangle, 69);  rectangle->set_color(rectangle, "green");  app->add_shape(app, (Shape *)rectangle);  // 再添加一个clone  app->add_shape(app, (Shape *)rectangle->clone(rectangle));}void app_add_shape(Application *app, Shape *shape){  app->shapes_length += 1;  Shape **new_shapes = (Shape **)calloc(app->shapes_length, sizeof(Shape));  // 复制原有数组,并追加新内容到新数组  for (int i = 0; i < app->shapes_length - 1; i++)  {    new_shapes[i] = app->shapes[i];  }  new_shapes[app->shapes_length - 1] = shape;  free(app->shapes);  // 指向新数组  app->shapes = new_shapes;}Shape *app_get_shape(Application *app, int index){  return app->shapes[index];}Shape **app_get_shapes(Application *app){  return app->shapes;}Shape *app_get_shape_clone(Application *app, int index){  Shape *shape = app->shapes[index];  if (shape != NULL)  {    return shape->clone(shape);  }  return NULL;}void app_print_shapes(Application *app){  for (int i = 0; i < app->shapes_length; i++)  {    Shape *shape = app->shapes[i];    printf("\r\n shape%d: %s", i, shape->to_string(shape));  }}// 给观察者绑定主题,同时把观察者添加到主题列表Application *application_constructor(){  printf("\r\n application_constructor() [构建Application]");  Application *app = (Application *)malloc(sizeof(Application));  app->shapes_length = 0;  app->shapes = (Shape **)calloc(app->shapes_length, sizeof(Shape));  app->add_to_shapes = &app_add_to_shapes;  app->add_shape = &app_add_shape;  app->get_shape = &app_get_shape;  app->get_shapes = &app_get_shapes;  app->get_shape_clone = &app_get_shape_clone;  app->print_shapes = &app_print_shapes;  return app;}
测试调用
#include "../src/func.h"int main(void){  printf("test start:\r\n");  /**   * 原型模式主要就是复制已有的对象,而无需实例化类,从而提升实例化对象时的性能   * 其实就是复制实例的属性到新对象上,减少了执行构造的步骤。   */  Application *application = application_constructor();  application->add_to_shapes(application);  Shape *shape_clone = application->get_shape_clone(application, 0);  // SetColor需要接口中定义  shape_clone->set_color(shape_clone, "gray");  printf("\r\n shape_clone : %s", shape_clone->to_string(shape_clone));  // 直接更改  // application->get_shape(application, 3)->set_color(application->get_shape(application, 3), "yellow");  application->print_shapes(application);  /*********************** 分割线 ******************************************/  // 追加一个Squre实例,相关属性为空  application->add_shape(application, (Shape *)square_constructor("square"));  // 打不打印查看结果  for (int i = 0; i < application->shapes_length; i++)  {    Shape *shape = application->shapes[i];    shape->draw(shape);    printf("\r\n shape_%d %s", i, shape->to_string(shape));  }}
更多语言版本

不同语言实现设计模式:https://github.com/microwind/design-pattern

猜你喜欢

【广东杭萧连签三单】近日,杭萧钢构(广东)有限公司(以下简称“广东杭萧”)成功签订金雨海洋智慧渔业产业园项目一期、东方傲立石化120万吨/年南海凝析油及轻烃综合利用生产基地及创新中心建设项目、定安县蜜雪冰城食品加工项目(一期)一标段等三个项目。三个项目均为海南自贸港集中开工项目,项目建成后将进一步推动海南自贸港经济高质量发展取得新成效。

2023-04-22 12:05:03

[ 最近更新 ]