找回密码
 立即注册
首页 业界区 业界 【原型设计模式详解】C/Java/JS/Go/Python/TS不同语言实 ...

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

司寇涵涵 2025-6-6 09:42:48
简介

原型模式(Prototype Pattern)是一种创建型设计模式,使你能够复制已有对象,而无需使代码依赖它们所属的类,同时又能保证性能。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
如果你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类,可以使用原型模式。
作用


  • 利用已有的一个原型对象,快速地生成和原型对象一样的实例。
  • 跳过构造函数的约束,便于提升性能。
实现步骤


  • 创建原型接口,并声明克隆方法。
  • 使用new运算符调用原型版本的构造函数。
  • 将子类构造函数的直接调用,替换为对原型工厂方法的调用。
UML

1.png
 
Java代码

基础原型抽象类
  1. // Shape.java 基础抽象类
  2. public abstract class Shape implements Cloneable {
  3.   private int width;
  4.   private int height;
  5.   private String color = "";
  6.   protected String type;
  7.   public Shape() {
  8.   }
  9.   public String getType() {
  10.     return type;
  11.   }
  12.   // 抽象方法,子类覆盖
  13.   public abstract void draw();
  14.   public void setWidth(int width) {
  15.     this.width = width;
  16.   }
  17.   public int getWidth() {
  18.     return this.width;
  19.   }
  20.   public int getHeight() {
  21.     return this.height;
  22.   }
  23.   public void setHeight(int height) {
  24.     this.height = height;
  25.   }
  26.   public void setColor(String color) {
  27.     this.color = color;
  28.   }
  29.   public String getColor() {
  30.     return this.color;
  31.   }
  32.   // 克隆方法
  33.   public Object clone() {
  34.     Object clone = null;
  35.     try {
  36.       clone = super.clone();
  37.     } catch (CloneNotSupportedException e) {
  38.       e.printStackTrace();
  39.     }
  40.     return clone;
  41.   }
  42.   @Override
  43.   public String toString() {
  44.     return String.format("{width = %s, height = %s, type = %s, color = %s }",
  45.         this.width, this.height, this.type, this.color);
  46.   }
  47. }
复制代码
具体原型者
  1. // Circle.java 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。
  2. public class Circle extends Shape {
  3.   public Circle() {
  4.     super();
  5.     type = "Circle";
  6.   }
  7.   @Override
  8.   public void draw() {
  9.     System.out.println("Circle::draw() method.");
  10.   }
  11. }
复制代码
  1. // Rectangle.java 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。
  2. public class Rectangle extends Shape {
  3.   public Rectangle() {
  4.     super();
  5.     type = "Rectangle";
  6.   }
  7.   @Override
  8.   public void draw() {
  9.      System.out.println("Rectangle::draw() method.");
  10.   }
  11. }
复制代码
  1. // 具体原型类,克隆方法会创建一个新对象并将其传递给构造函数。
  2. public class Square extends Shape {
  3.   public Square() {
  4.     super();
  5.     type = "Square";
  6.   }
  7.   @Override
  8.   public void draw() {
  9.     System.out.println("Square::draw() method.");
  10.   }
  11. }
复制代码
客户使用类
  1. // Application.java 客户调用方
  2. public class Application {
  3.   public List<Shape> shapes = new ArrayList<Shape>();
  4.   public Application() {
  5.   }
  6.   public void addToShapes() {
  7.     Circle circle = new Circle();
  8.     circle.setWidth(10);
  9.     circle.setHeight(20);
  10.     circle.setColor("red");
  11.     shapes.add(circle);
  12.     // 添加clone
  13.     Circle anotherCircle = (Circle) circle.clone();
  14.     anotherCircle.setColor("pink");
  15.     shapes.add(anotherCircle);
  16.     // 变量 `anotherCircle(另一个圆)`与 `circle(圆)`对象的内容完全一样。
  17.     Rectangle rectangle = new Rectangle();
  18.     rectangle.setWidth(99);
  19.     rectangle.setHeight(69);
  20.     rectangle.setColor("green");
  21.     shapes.add(rectangle);
  22.     // 添加clone
  23.     shapes.add((Shape) rectangle.clone());
  24.   }
  25.   // 直接取出
  26.   public Shape getShape(Integer index) {
  27.     return this.shapes.get(index);
  28.   }
  29.   // 取出时候clone
  30.   public Shape getShapeClone(Integer index) {
  31.     Shape shape = this.shapes.get(index);
  32.     return (Shape) shape.clone();
  33.   }
  34.   public void printShapes() {
  35.     for (int i = 0; i < this.shapes.size(); i++) {
  36.       Shape shape = this.shapes.get(i);
  37.       System.out.println("shape " + i + " : " + shape.toString());
  38.     }
  39.   }
  40. }
复制代码
测试调用
  1.     /**
  2.      * 原型模式主要就是复制已有的对象,而无需实例化类,从而提升实例化对象时的性能
  3.      * 其实就是复制实例的属性到新对象上,减少了执行构造的步骤
  4.      */
  5.     Application application = new Application();
  6.     application.addToShapes();
  7.     Shape shapeClone = application.getShapeClone(1);
  8.     // 更改clone
  9.     shapeClone.setColor("gray");
  10.     System.out.println("shapeClone : " + shapeClone.toString());
  11.     // 直接更改
  12.     application.getShape(3).setColor("yellow");
  13.     application.printShapes();
  14.     // /*********************** 分割线 ******************************************/
  15.     application.shapes.add(new Square());
  16.     for (Shape shape : application.shapes) {
  17.       shape.draw();
  18.       System.out.println(shape.toString());
  19.     }
复制代码
C代码

基础原型抽象类
  1. // func.h 基础头文件
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7. typedef struct Shape shape;
  8. typedef struct Circle circle;
  9. typedef struct Rectangle rectangle;
  10. typedef struct Square square;
  11. // 定义了Shape作为基础接口,以便各形状有统一类型
  12. typedef struct Shape
  13. {
  14.     char name[50];
  15.     int width;
  16.     int height;
  17.     char color[50];
  18.     char category[50];
  19.     void (*draw)(struct Shape *shape);
  20.     struct Shape *(*clone)(struct Shape *shape);
  21.     char *(*to_string)(struct Shape *shape);
  22.     void (*set_width)(struct Shape *shape, int width);
  23.     int (*get_width)(struct Shape *shape);
  24.     void (*set_height)(struct Shape *shape, int height);
  25.     int (*get_height)(struct Shape *shape);
  26.     void (*set_color)(struct Shape *shape, char *color);
  27.     char *(*get_color)(struct Shape *shape);
  28.     void (*set_category)(struct Shape *shape, char *category);
  29.     char *(*get_category)(struct Shape *shape);
  30. } Shape;
  31. Shape *shape_constructor(char *name);
  32. typedef struct Circle
  33. {
  34.     char name[50];
  35.     int width;
  36.     int height;
  37.     char color[50];
  38.     char category[50];
  39.     void (*draw)(struct Circle *shape);
  40.     struct Circle *(*clone)(struct Circle *shape);
  41.     char *(*to_string)(struct Circle *shape);
  42.     void (*set_width)(struct Circle *shape, int width);
  43.     int (*get_width)(struct Circle *shape);
  44.     void (*set_height)(struct Circle *shape, int height);
  45.     int (*get_height)(struct Circle *shape);
  46.     void (*set_color)(struct Circle *shape, char *color);
  47.     char *(*get_color)(struct Circle *shape);
  48.     void (*set_category)(struct Circle *shape, char *category);
  49.     char *(*get_category)(struct Circle *shape);
  50. } Circle;
  51. Circle *circle_constructor(char *name);
  52. typedef struct Square
  53. {
  54.     char name[50];
  55.     int width;
  56.     int height;
  57.     char color[50];
  58.     char category[50];
  59.     void (*draw)(struct Square *shape);
  60.     struct Square *(*clone)(struct Square *shape);
  61.     char *(*to_string)(struct Square *shape);
  62.     void (*set_width)(struct Square *shape, int width);
  63.     int (*get_width)(struct Square *shape);
  64.     void (*set_height)(struct Square *shape, int height);
  65.     int (*get_height)(struct Square *shape);
  66.     void (*set_color)(struct Square *shape, char *color);
  67.     char *(*get_color)(struct Square *shape);
  68.     void (*set_category)(struct Square *shape, char *category);
  69.     char *(*get_category)(struct Square *shape);
  70. } Square;
  71. Square *square_constructor(char *name);
  72. typedef struct Rectangle
  73. {
  74.     char name[50];
  75.     int width;
  76.     int height;
  77.     char color[50];
  78.     char category[50];
  79.     void (*draw)(struct Rectangle *shape);
  80.     struct Rectangle *(*clone)(struct Rectangle *shape);
  81.     char *(*string)(struct Rectangle *shape);
  82.     void (*set_width)(struct Rectangle *shape, int width);
  83.     int *(*get_width)(struct Rectangle *shape);
  84.     void (*set_height)(struct Rectangle *shape, int height);
  85.     int *(*get_height)(struct Rectangle *shape);
  86.     void (*set_color)(struct Rectangle *shape, char *color);
  87.     char *(*get_color)(struct Rectangle *shape);
  88.     void (*set_category)(struct Rectangle *shape, char *category);
  89.     char *(*get_category)(struct Rectangle *shape);
  90. } Rectangle;
  91. Rectangle *rectangle_constructor(char *name);
  92. // 调用客户端
  93. typedef struct Application
  94. {
  95.     struct Shape **shapes;
  96.     int shapes_length;
  97.     void (*add_to_shapes)(struct Application *app);
  98.     void (*add_shape)(struct Application *app, Shape *shape);
  99.     Shape *(*get_shape)(struct Application *app, int index);
  100.     Shape **(*get_shapes)(struct Application *app);
  101.     Shape *(*get_shape_clone)(struct Application *app, int index);
  102.     void (*print_shapes)(struct Application *app);
  103. } Application;
  104. Application *application_constructor();
复制代码
  1. // shape.c 基础类,供各种具体形状复用
  2. #include "func.h"
  3. // shape基础抽象类,供子类继承覆盖
  4. // C没有抽象和继承,此处作为公共类存在
  5. void shape_draw(Shape *shape)
  6. {
  7.   printf("\r\n Shape::draw()");
  8. }
  9. void shape_set_width(Shape *shape, int width)
  10. {
  11.   shape->width = width;
  12. }
  13. int shape_get_width(Shape *shape)
  14. {
  15.   return shape->width;
  16. }
  17. int shape_get_height(Shape *shape)
  18. {
  19.   return shape->height;
  20. }
  21. void shape_set_height(Shape *shape, int height)
  22. {
  23.   shape->height = height;
  24. }
  25. void shape_set_color(Shape *shape, char *color)
  26. {
  27.   strncpy(shape->color, color, 50);
  28. }
  29. char *shape_get_color(Shape *shape)
  30. {
  31.   return shape->color;
  32. }
  33. void shape_set_category(Shape *shape, char *category)
  34. {
  35.   strncpy(shape->category, category, 50);
  36. }
  37. char *shape_get_category(Shape *shape)
  38. {
  39.   return shape->category;
  40. }
  41. char *shape_to_string(Shape *shape)
  42. {
  43.   static char result[1024];
  44.   sprintf(result, "[name = %s width = %d, height = %d, category = %s, color = %s]",
  45.           shape->name, shape->width, shape->height, shape->category, shape->color);
  46.   return result;
  47. }
  48. // 将指针指向同一内存的方式来实现clone
  49. Shape *shape_clone(Shape *shape)
  50. {
  51.   Shape *copy = (Shape *)malloc(sizeof(Shape));
  52.   memcpy(copy, shape, sizeof(Shape));
  53.   strcat(copy->name, "(clone)");
  54.   // printf("\r\n shape_clone: %s", copy->to_string(copy));
  55.   return copy;
  56. }
  57. // 定义简单结构体,复制基本属性和draw函数
  58. Shape *shape_clone2(Shape *shape)
  59. {
  60.   struct Shape copy = {
  61.       .width = shape->width,
  62.       .height = shape->height,
  63.   };
  64.   strcpy(copy.name, shape->name);
  65.   strcat(copy.name, "[clone]");
  66.   strcpy(copy.color, shape->color);
  67.   strcpy(copy.category, shape->category);
  68.   Shape *shape_copy = ©
  69.   shape_copy->draw = shape->draw;
  70.   // printf("\r\n shape_clone: %s", shape->to_string(shape_copy));
  71.   return shape_copy;
  72. }
  73. Shape *shape_constructor(char *name)
  74. {
  75.   printf("\r\n shape_constructor() [构建Shape]");
  76.   Shape *shape = (Shape *)malloc(sizeof(Shape));
  77.   strncpy(shape->name, name, 50);
  78.   shape->draw = &shape_draw;
  79.   shape->clone = &shape_clone;
  80.   shape->to_string = &shape_to_string;
  81.   shape->set_width = &shape_set_width;
  82.   shape->get_width = &shape_get_width;
  83.   shape->set_height = &shape_set_height;
  84.   shape->get_height = &shape_get_height;
  85.   shape->set_color = &shape_set_color;
  86.   shape->get_color = &shape_get_color;
  87.   shape->set_category = &shape_set_category;
  88.   shape->get_category = &shape_get_category;
  89.   return shape;
  90. }
复制代码
具体原型者
  1. // circle.c 具体原型类,复用父类方法,实现自己的draw函数。
  2. #include "func.h"
  3. // 重新定义draw函数
  4. void circle_draw(Circle *shape)
  5. {
  6.   printf("\r\n Circle::draw()");
  7. }
  8. Circle *circle_constructor(char *name)
  9. {
  10.   printf("\r\n shape_constructor() [构建Circle]");
  11.   Shape *shape = (Shape *)shape_constructor(name);
  12.   Circle *circle = (Circle *)shape;
  13.   circle->draw = &circle_draw;
  14.   return circle;
  15. }
复制代码
  1. // rectangle.c 具体原型类,复用父类方法,实现自己的draw函数。
  2. #include "func.h"
  3. // 重新定义draw函数
  4. void rectangle_draw(Rectangle *shape)
  5. {
  6.   printf("\r\n Rectangle::draw()");
  7. }
  8. Rectangle *rectangle_constructor(char *name)
  9. {
  10.   printf("\r\n shape_constructor() [构建Rectangle]");
  11.   Shape *shape = (Shape *)shape_constructor(name);
  12.   Rectangle *rectangle = (Rectangle *)shape;
  13.   rectangle->draw = &rectangle_draw;
  14.   return rectangle;
  15. }
复制代码
  1. // square.c 具体原型类,复用父类方法,实现自己的draw函数。
  2. #include "func.h"
  3. // 重新定义draw函数
  4. void square_draw(Square *shape)
  5. {
  6.   printf("\r\n Square::draw()");
  7. }
  8. Square *square_constructor(char *name)
  9. {
  10.   printf("\r\n shape_constructor() [构建Square]");
  11.   Shape *shape = (Shape *)shape_constructor(name);
  12.   Square *square = (Square *)shape;
  13.   square->draw = &square_draw;
  14.   return square;
  15. }
复制代码
客户使用类
  1. // application.c 客户调用方
  2. #include "func.h"
  3. void app_add_to_shapes(Application *app)
  4. {
  5.   Circle *circle = circle_constructor("circle");
  6.   circle->set_category(circle, "Circle");
  7.   circle->set_width(circle, 10);
  8.   circle->set_height(circle, 20);
  9.   circle->set_color(circle, "red");
  10.   app->add_shape(app, (Shape *)circle);
  11.   // 添加Clone
  12.   Circle *another_circle = circle->clone(circle);
  13.   another_circle->set_color(another_circle, "pink");
  14.   app->add_shape(app, (Shape *)another_circle);
  15.   // 变量 `another_circle(另一个圆)`与 `circle(圆)`对象的内容完全一样。
  16.   Rectangle *rectangle = rectangle_constructor("rectangle");
  17.   rectangle->set_category(rectangle, "Rectangle");
  18.   rectangle->set_width(rectangle, 99);
  19.   rectangle->set_height(rectangle, 69);
  20.   rectangle->set_color(rectangle, "green");
  21.   app->add_shape(app, (Shape *)rectangle);
  22.   // 再添加一个clone
  23.   app->add_shape(app, (Shape *)rectangle->clone(rectangle));
  24. }
  25. void app_add_shape(Application *app, Shape *shape)
  26. {
  27.   app->shapes_length += 1;
  28.   Shape **new_shapes = (Shape **)calloc(app->shapes_length, sizeof(Shape));
  29.   // 复制原有数组,并追加新内容到新数组
  30.   for (int i = 0; i < app->shapes_length - 1; i++)
  31.   {
  32.     new_shapes[i] = app->shapes[i];
  33.   }
  34.   new_shapes[app->shapes_length - 1] = shape;
  35.   free(app->shapes);
  36.   // 指向新数组
  37.   app->shapes = new_shapes;
  38. }
  39. Shape *app_get_shape(Application *app, int index)
  40. {
  41.   return app->shapes[index];
  42. }
  43. Shape **app_get_shapes(Application *app)
  44. {
  45.   return app->shapes;
  46. }
  47. Shape *app_get_shape_clone(Application *app, int index)
  48. {
  49.   Shape *shape = app->shapes[index];
  50.   if (shape != NULL)
  51.   {
  52.     return shape->clone(shape);
  53.   }
  54.   return NULL;
  55. }
  56. void app_print_shapes(Application *app)
  57. {
  58.   for (int i = 0; i < app->shapes_length; i++)
  59.   {
  60.     Shape *shape = app->shapes[i];
  61.     printf("\r\n shape%d: %s", i, shape->to_string(shape));
  62.   }
  63. }
  64. // 给观察者绑定主题,同时把观察者添加到主题列表
  65. Application *application_constructor()
  66. {
  67.   printf("\r\n application_constructor() [构建Application]");
  68.   Application *app = (Application *)malloc(sizeof(Application));
  69.   app->shapes_length = 0;
  70.   app->shapes = (Shape **)calloc(app->shapes_length, sizeof(Shape));
  71.   app->add_to_shapes = &app_add_to_shapes;
  72.   app->add_shape = &app_add_shape;
  73.   app->get_shape = &app_get_shape;
  74.   app->get_shapes = &app_get_shapes;
  75.   app->get_shape_clone = &app_get_shape_clone;
  76.   app->print_shapes = &app_print_shapes;
  77.   return app;
  78. }
复制代码
测试调用
  1. #include "../src/func.h"
  2. int main(void)
  3. {
  4.   printf("test start:\r\n");
  5.   /**
  6.    * 原型模式主要就是复制已有的对象,而无需实例化类,从而提升实例化对象时的性能
  7.    * 其实就是复制实例的属性到新对象上,减少了执行构造的步骤。
  8.    */
  9.   Application *application = application_constructor();
  10.   application->add_to_shapes(application);
  11.   Shape *shape_clone = application->get_shape_clone(application, 0);
  12.   // SetColor需要接口中定义
  13.   shape_clone->set_color(shape_clone, "gray");
  14.   printf("\r\n shape_clone : %s", shape_clone->to_string(shape_clone));
  15.   // 直接更改
  16.   // application->get_shape(application, 3)->set_color(application->get_shape(application, 3), "yellow");
  17.   application->print_shapes(application);
  18.   /*********************** 分割线 ******************************************/
  19.   // 追加一个Squre实例,相关属性为空
  20.   application->add_shape(application, (Shape *)square_constructor("square"));
  21.   // 打不打印查看结果
  22.   for (int i = 0; i < application->shapes_length; i++)
  23.   {
  24.     Shape *shape = application->shapes[i];
  25.     shape->draw(shape);
  26.     printf("\r\n shape_%d %s", i, shape->to_string(shape));
  27.   }
  28. }
复制代码
更多语言版本

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

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册