跟着老侯玩编程 跟着老侯玩编程
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
  • 基础语法

    • 单元文件
    • 变量和常量
    • 内联变量
    • 基本数据类型
    • 复合数据类型
    • 语句(选择语句)
    • 语句(循环语句)
    • 数组
    • 初识例程
    • 初识面向对象
    • 属性Property
    • 面向对象的方法
    • 指针
    • 接口
    • 匿名函数和委托实现
    • 多态
    • 字符串详解
    • 异常处理
    • 反射机制
    • 泛型容器
    • JSON
    • 文件操作
    • Dll创建并调用
    • DLL初始化和退出处理
    • Package
    • 理解消息循环
    • VCL与Windows消息
    • 钩子原理
    • 进程通讯-内存映像
    • 多线程开篇
    • 线程控制
    • 线程同步
  • 网络编程

    • 网络编程基础
    • Delphi网络编程
    • select
    • WSAAsyncSelect
    • WSAEventSelect
  • 设计模式

    • 单例模式
    • 单例模式二
    • 策略模式
    • 简单工厂模式
    • 建造者模式
    • 原型模式
      • 举个例子
      • 提个需求
      • 代码实现
      • 结语
    • 模板方法模式
    • 状态模式
    • 迭代器模式
    • 解释器模式
    • 责任链模式
    • 中介者模式
    • 备忘录模式
    • 命令模式
    • 观察者模式
    • 访问者模式
    • 适配器模式
    • 桥接模式
  • Delphi
  • 设计模式
舞动的代码
2022-05-05
目录

原型模式

这篇文章聊聊原型模式,官方给的定义如下:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

有没有这样一种感觉?写的都是中文自己也认识,但是组合在一起完全不知道说的是什么意思。其实简单的说就是“克隆”

它的适用场景如下

  1. 当一个系统应该独立于它的产品创建、构成和表示时。

  2. 当要实例化的类是在运行时刻指定时,例如,通过动态装载。

  3. 为了避免创建一个与产品类层次平行的工厂类层次时。

  4. 当一个类的实例只能有几个不同状态组合中的一种时。

  5. 建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

很明显适用场景是我从文档上复制的

# 举个例子

其实这种设计模式我们每天都在用,当然可能不是写代码用。我在窗体上创建一个按钮,并对这个按钮复制粘贴多次,于是就有了下图的样子。

那么我的问题是你复制的是按钮的什么东西?其实我们是通过复制粘贴的动作完成了对现有按钮的克隆操作。而克隆的是按钮的整个对象

有朋友可能会提出疑问,这个复制粘贴也不需要我们来写啊。这不是已经有了嘛。好,那么接着往下看

# 提个需求

学校要给学生颁发”三好学生“的奖状,现在需要设计一下代码该如何实现这一操作

简单分析下

同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个“三好学生”奖状出来,然后在修改奖状上的名字即可

其实这就是原型模式的一个应用场景。比较尴尬的是 Delphi 不想其他编程语言提供了对象的克隆功能(比如:Java 有Object.clone方法),所以在 Delphi 中实现对象的克隆功能需要自己编写代码

万幸的是VCL的体系结构中的 TPersistent 类有一个 Assign 方法(这是一个过程),该方法叫常用于两个对象属性的复制。其代码如下,所在的单元 System.Classes

procedure TPersistent.Assign(Source: TPersistent);
begin
  if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;
1
2
3
4

在官方文档中有这么一段描述

The Assign method of TPersistent calls AssignTo if the descendant object does not succeed in copying the properties of a source object. The AssignTo method defined by TPersistent raises an EConvertError exception.

译文:如果Descendant对象未成功复制源对象的属性,则TPersistent调用的分配方法。 由TPersistent定义的分配方法引发了一个异常异常。

其实没有看太懂,只是看明白了会报异常。但是在”Delphi模式编程“一书上看到一段说明,如果由 AssignedTo 方法来实现复制,那么必须保证源对象的类已经重写了 AssignedTo 方法,否则会抛出 AssignError 异常

# 代码实现


unit UnitPrototype;

interface

uses
    System.Classes;

type
    TPrototype = class(TPersistent)
    protected
        //自己实现克隆的函数
        function Clone: TPrototype; virtual; abstract;
    end;

    TCitation = class(TPrototype)
    private
        FName: string;
    public

        property Name: string read FName write FName;

        //重写父类的方法
        procedure Assign(Source: TPersistent); override;

        function Clone: TPrototype; override;
    end;

implementation

{ TConcreatePrototype1 }

procedure TCitation.Assign(Source: TPersistent);
begin
    //类型转换并完成属性赋值
    if Source is TCitation then begin

        with Source as TCitation do begin

            self.Name := Name;

        end;

    end
    else begin
        inherited;
    end;

end;



function TCitation.Clone: TPrototype;
begin

    //此处的 Result 所代表的为 目标(target)
    Result := TCitation.Create;

    //将 源 复制到 目标并返回
    Result.Assign(self);
end;

end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

调用

program Prototype;

{$APPTYPE CONSOLE}

{$R *.res}

uses
    System.SysUtils,
    UnitPrototype in 'UnitPrototype.pas';

begin
    var Citation := TCitation.Create();
    Citation.Name := '小黑';
    //Writeln(Integer(@Citation).ToHexString);

    Writeln(Citation.Name+'同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!');

    //克隆一个对象
    var Citation1 := Citation.Clone();

    //在没有重新赋值之前,克隆出来的对象保持原来的值
    Writeln(Citation.Name);

    Readln;
end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 结语

这篇文章是设计模式中创建型模式全部梳理完成了。又来新的授课任务了,不知道后面还能不能维持正常的文章更新。。。

建造者模式
模板方法模式

← 建造者模式 模板方法模式→

Theme by Vdoing | Copyright © 2013-2023 冀ICP备16006233号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×