手撕设计模式——克隆对象之原型模式

手撕设计模式——克隆对象之原型模式

1.业务需求

​ 大家好,我是菠菜啊,前俩天有点忙,今天继续更新了。今天给大家介绍克隆对象——原型模式。老规矩,在介绍这期之前,我们先来看看这样的需求:《西游记》中每次孙悟空拔出一撮猴毛吹一下,变出一大批猴子加入战斗,他到底是怎么变的?如果我们帮他实现这个功能,代码怎么设计?

孙悟空拔毛变猴

2.代码实现

Talk is cheap,show me your code.

首先先说第一个问题,怎么变的我也不知道。

表情包-我不知道

但是第二个问题,可以尝试一下。

实现初步思路:

​ 我们新建一个猴子类,并且实例化多个猴子对象不就行了,太简单了。

Monkey类:

//猴子
public class Monkey {

    private String name;
    private String sex;
    private int age;
    private Weapon weapon;

    public Monkey(String name, String sex, int age, Weapon weapon) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.weapon = weapon;
    }

    public Weapon getWeapon() {
        return weapon;
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    @Override
    public String toString() {
        return "Monkey{" +
                "name='" + name + ''' +
                ", sex='" + sex + ''' +
                ", age=" + age +
                ", weapon=" + weapon +
                '}';
    }
}

Weapon类:

//武器
public class Weapon {

    private String name;
    private String color;

    public Weapon(String name, String color) {
        this.name = name;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Weapon{" +
                "name='" + name + ''' +
                ", color='" + color + ''' +
                '}';
    }
}

Client类:

public class Client {
    public static void main(String[] args) {
        Weapon weapon=new Weapon("金箍棒","金色");
        Monkey monkey=new Monkey("孙悟空","公",20,weapon);

        Weapon weapon2=new Weapon(monkey.getWeapon().getName(),monkey.getWeapon().getColor());
        Monkey monkey2=new Monkey("猴小弟",monkey.getSex(),monkey.getAge(),weapon2);

        Weapon weapon3=new Weapon(monkey.getWeapon().getName(),monkey.getWeapon().getColor());
        Monkey monkey3=new Monkey("猴小小弟",monkey.getSex(),monkey.getAge(),weapon3);

        System.out.println(monkey);
        System.out.println(monkey2);
        System.out.println(monkey3);

    }
}

思考:上述代码比较简单,功能是实现了,但是在克隆猴哥的时候,我们要将新建一个相同类的对象。 然后, 我还要必须遍历原始对象的所有成员变量, 并将成员变量值复制到新对象中。这也太麻烦了,如果属性是上千上万个,那么猴哥还没变出猴子,师傅就被妖怪给吃了。 而且并非所有对象都能通过这种方式进行复制, 因为有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的。而且克隆对象,要知道该对象类的所有依赖类才行,这样设计也太不符合迪米特法则了(详细见《设计模式——设计原则介绍》一文)。

3.方案改进

​ Java中提供了一个Cloneable接口,其中有一个clone()方法,我们只要实现这个方法就行了。

实现代码结构图

原型模式之悟空变猴子.drawio

Monkey接口:

//猴子
public class Monkey implements Cloneable{

   //......

    @Override
    protected Monkey clone() throws CloneNotSupportedException {
        return (Monkey)super.clone();
    }

}

Client类:

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Weapon weapon=new Weapon("金箍棒","金色");
        Monkey monkey=new Monkey("孙悟空","公",20,weapon);

       /* Weapon weapon2=new Weapon(monkey.getWeapon().getName(),monkey.getWeapon().getColor());
        Monkey monkey2=new Monkey("猴小弟",monkey.getSex(),monkey.getAge(),weapon2);

        Weapon weapon3=new Weapon(monkey.getWeapon().getName(),monkey.getWeapon().getColor());
        Monkey monkey3=new Monkey("猴小小弟",monkey.getSex(),monkey.getAge(),weapon3);*/
        Monkey monkey2=monkey.clone();
        monkey2.setName("猴小弟");
        Monkey monkey3=monkey.clone();
        monkey3.setName("猴小小弟");

        System.out.println(monkey);
        System.out.println(monkey2);
        System.out.println(monkey3);

    }
}

思考:这样我们就可以快速克隆对象,并且不需要知道对象创建的细节,又大大提高了性能,我们把这种设计模式叫做原型模式(Prototype )。上述代码还是有问题,可以继续往下看。

拓展:浅克隆和深克隆

​ 我们把上述代码稍微修改一下,看的就明显了。

Client修改后:

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Weapon weapon=new Weapon("金箍棒","金色");
        Monkey monkey=new Monkey("孙悟空","公",20,weapon);

        Monkey monkey2=monkey.clone();
        monkey2.setName("猴小弟");
        Monkey monkey3=monkey.clone();
        monkey3.setName("猴小小弟");

        System.out.println("修改武器前:"+monkey);
        System.out.println("修改武器前:"+monkey2);
        System.out.println("修改武器前:"+monkey3);
        //修改各自的武器装备
        monkey.getWeapon().setColor("红色");
        monkey2.getWeapon().setColor("白色");
        monkey3.getWeapon().setColor("绿色");

        System.out.println("++++++修改武器+++++");

        System.out.println("修改武器后:"+monkey);
        System.out.println("修改武器后:"+monkey2);
        System.out.println("修改武器后:"+monkey3);

    }
}

预期结果:猴子们的武器颜色分别是红白绿。

实际结果:猴子们的武器都被绿了(一不小心开车了)。

深复制和浅复制结果图

排查原因发现,super.clone(),如果字段是值类型的,就复制值,如果字段是引用类型的,复制引用而不复制引用的对象(String是特殊的引用对象),因此猴子们引用的武器对象是一个。被复制的对象的所有变量值都含有原来对象相同的值,但是其它对象的引用仍然执行原来的对象,叫做浅克隆。反之,把引用对象的变量指向复制过的新对象,这种叫做深克隆

我们如果要完成深复制,只需做如下修改:

Weapon类:

//武器
public class Weapon implements Cloneable{

    //...

    @Override
    protected Weapon clone() throws CloneNotSupportedException {
        return (Weapon)super.clone();
    }

}

Monkey类:

public class Monkey implements Cloneable{

    //...
    @Override
    protected Monkey clone() throws CloneNotSupportedException {
        Monkey clone= (Monkey)super.clone();
        clone.weapon=this.weapon.clone();
        return clone;
    }

}

思考:如果要深克隆,必须重写clone方法,如果克隆对象依赖对象的层级嵌套一多,代码较复杂。

4.定义和组成结构

原型模式.drawio

原型模式(Prototype)从一个对象创建一个可定制的对象,而不需要知道任何创建细节。

​ 原型模式包含以下主要角色。

  • 抽象原型类(Prototype):规定了具体原型对象必须实现的接口。
  • 具体原型类(ConcretePrototype):实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类(Acess):使用具体原型类中的 clone() 方法来复制新的对象。

5.优缺点以及应用场景

优点:

  • 通过克隆一个已有的对象,简化对象的创建过程,不用关注对象的内部创建细节,符合迪米特法则
  • 流的方式比new一个对象克隆对象效率更高

缺点:

  • 克隆对象类必须要重写clone方法
  • 如果克隆对象依赖对象的嵌套层级较多,并且要达到深克隆,代码较复杂
  • clone 方法位于类的内部,当对已有类进行改造的时候,可能需要修改代码,违背了开闭原则

适用场景:

  • 保存对象的状态并且对象占用内存较少
  • 对象创建成本高,耗用的资源比较多
  • 对象初始化复杂

技术需要沉淀,同样生活也是~
个人链接:博客,欢迎一起交流

评论

  1. 5 月前
    2026-4-25 4:46:18

    Really interesting read! Seeing platforms like p898 app casino focus on RTP & fair play (with that RNG tech!) is a huge step forward. Variance control sounds key for a good experience, too. 👍

  2. 2 月前
    2026-7-08 8:53:28

    The UX flow you detailed is solid; optimizing touch points like the rwwin app experience shows real fund management foresight. Check out rwwin link for more insights.

  3. 1 月前
    2026-8-03 22:31:34

    Great article! The speed of transactions is key for online gaming here. I’ve heard okpl download apk is really fast with GCash & PayMaya – security is a big plus too, right? Definitely checking that out! 👍

  4. 1 月前
    2026-8-07 17:16:32

    This deep dive into the Prototype Pattern highlights the critical importance of consistent state replication. Whether modeling a mythical creature or managing complex financial systems, reliable architecture is key. In strategic domains, maintaining system integrity is paramount, which is why finding a trustworthy platform like casino game legit is so essential.

  5. 3 周前
    2026-8-18 6:10:12

    The Prototype Pattern is a brilliant analogy for systemic scalability. Beyond code, it mirrors how complex systems-like modern gaming ecosystems-must replicate core functionalities (e.g., user profiles, game states) instantly and reliably. Thinking about state cloning efficiency is key to maintaining high performance, whether in software architecture or in optimizing user experiences at platforms like nk77 com.

  6. 1 天前
    2026-9-08 17:22:13

    Just joined Shooter Game for some Filipino slots action! The GCash integration is smooth, and I’m ready to dive into live casino fun via Shooter Game slot download. Can’t wait to play with this community today!

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇