首页 > 其他分享 >设计模式[3]-原型模式

设计模式[3]-原型模式

时间:2024-08-23 11:04:40浏览次数:14  
标签:name Color clone dog 模式 Dog 原型 设计模式 dog2

代码:https://gitee.com/Aes_yt/design-pattern

原型模式

概念

原型模式将一个已经创建的实例作为原型,复制出一个和原型相同的新对象。

包括三种角色:

  • 抽象原型:抽象角色,提供具体原型需要实现的接口
  • 具体原型:被复制的对象,实现抽象原型的接口
  • 客户端:发出创建对象的请求。

例子:

先看一个简单的例子,我们设计一个Cloneable接口作为抽象原型,一个Dog类作为具体原型,Dog类关联一个Color类,然后用测试类做客户端来准备复制对象。

image-20211213225141050

Cloneable:

public interface Cloneable<T> {
    T clone();
}

Color:

@Data
public class Color {
    private String name;

    public Color(String name) {
        this.name = name;
    }
}

Dog:

@Data
public class Dog implements Cloneable<Dog> {
    private String name;
    private Color color;

    public Dog() {
        System.out.println("Dog 构造函数。");
    }

    @Override
    public Dog clone() {
        Dog dog = new Dog();
        dog.setColor(this.color);
        dog.setName(this.name);
        return dog;
    }
}

DogTest:

class DogTest {
    @Test
    void show() {
        Dog dog = new Dog();
        dog.setName("小白");
        dog.setColor(new Color("白色"));

        Dog dog2 = dog.clone();
        System.out.println(dog == dog2);
        System.out.println(dog.getColor() == dog2.getColor());

        System.out.println("dog:" + dog.getColor().getName());
        System.out.println("dog2:" + dog2.getColor().getName());

        dog.getColor().setName("黑色");

        System.out.println("dog:" + dog.getColor().getName());
        System.out.println("dog2:" + dog2.getColor().getName());
    }
}

输出:

Dog 构造函数。
Dog 构造函数。
false
true
dog:白色
dog2:白色
dog:黑色
dog2:黑色

分析

首先,我们创建了一个Cloneable接口,然后创建Dog类的实现实现这个接口 ,重写clone()方法,来表示这个类是采用原型模式,这个类可以被复制。

具体的复制方法,在clone()方法中,实例化了Dog类,并赋值给新类。

从DogTest中我们发现了,dog实例对象和复制出来的dog2实例对象是不相等的,说明这是两个类,但是,我们发现了,dog.getColor() 和 dog2.getColor()其实指向的是同一个地址。这就是浅拷贝,只拷贝了数值或者对象的地址,这种情况下,对dog的color做出修改会影响到dog2的color对象的内容。

改进

首先,可以将Color类也实现Cloneable接口,重写clone接口。

@Data
public class Color implements Cloneable<Color>{
    private String name;

    public Color(String name) {
        this.name = name;
    }

    @Override
    public Color clone() {
        return new Color(this.name);
    }
}

然后,修改Dog类的clone方法,对Color的对象进行clone。

Dog:

    @Override
    public Dog clone() {
        Dog dog = new Dog();
//        dog.setColor(this.color);
        dog.setColor(this.color.clone());
        dog.setName(this.name);
        return dog;
    }

最后执行测试类,输出:

Dog 构造函数。
Dog 构造函数。
false
false
dog:白色
dog2:白色
dog:黑色
dog2:白色

结果第四行 dog.getColor() == dog2.getColor() 的输出是false,第7行,dog改变颜色变成黑色,没有影响到第8行dog2的白色。拷贝成功。

拓展

java中也有用到原型模式,java.lang.Object 中就有 clone 方法,所以一个对象只需要实现 java.lang.Cloneable接口,然后调用Object类中的clone方法,即可完成对象的拷贝。但是Object类中的clone方法是浅拷贝,而且实现并不是通过像上面的例子一样,通过构造方法直接实例化一个对象出来。

利用自带的Clone方法,实现浅拷贝,代码如下:

@Data
public class Dog implements java.lang.Cloneable {
    private String name;
    private Color color;

    public Dog() {
        System.out.println("Dog 构造函数。");
    }

    @Override
    public Dog clone() throws CloneNotSupportedException {
        return (Dog)super.clone();
    }
}

深拷贝利用Color类的clone方法,或者通过对象的序列化实现,就不细说了。

标签:name,Color,clone,dog,模式,Dog,原型,设计模式,dog2
From: https://www.cnblogs.com/Aeons/p/18375610

相关文章

  • 设计模式[2]-工厂模式
    代码:https://gitee.com/Aes_yt/design-pattern工厂模式1.简单工厂模式简单工厂模式主要包括三种角色:简单工厂:创建具体产品抽象产品:具体产品的父类具体产品:简单工厂创建的对象例子:设计一个游戏机类(GameConsole)作为抽象产品,然后设计具体的产品(PlanStation4,Xb......
  • 设计模式[1]-单例模式
    代码:https://gitee.com/Aes_yt/design-pattern单例模式单例模式(Singleton)是一种创建型设计模式,能够保证一个类只有一个实例,并提供了访问该实例的全局节点。单例的实现步骤有以下步骤,首先将默认构造函数设置为私有,然后创建一个静态方法来调用私有构造函数来创建对象。单例类......
  • Scratch编程环境的暗色模式:探索可访问性的边界
    标题:Scratch编程环境的暗色模式:探索可访问性的边界Scratch,这个广受欢迎的图形化编程平台,由麻省理工学院媒体实验室开发,一直致力于为用户提供友好且易于访问的编程体验。随着用户对编程环境个性化需求的增长,Scratch的编程环境是否支持暗模式或可访问性选项,成为了编程教育领......
  • C++设计模式1:单例模式(懒汉模式和饿汉模式,以及多线程问题处理)
    饿汉单例模式        程序还没有主动获取实例对象,该对象就产生了,也就是程序刚开始运行,这个对象就已经初始化了。 classSingleton{public: ~Singleton() { std::cout<<"~Singleton()"<<std::endl; } staticSingleton*get_instance() { return&sin......
  • 火影忍者2——漩涡鸣人(仙人模式)篇
    老规矩,谈火影~火影忍者之——漩涡鸣人(仙人模式)篇众所周知,鸣仙是一个早期的A忍,技能破坏力贼大,一般遇到鸣仙(除非我用了青水+神卡)我是直接退的普攻一技能螺旋丸普通状态下一技能长摁放出两个分身释放螺旋丸,属于远程技能,但释放时的施法动作容易被打断,点击是本体出去,......
  • Java设计模式之代理模式:静态代理VS动态代理,与其他模式的对比分析和案例解析
    一、代理模式简介代理模式(ProxyPattern)是一种结构型设计模式,它提供了一个代理对象,用来控制对另一个对象的访问。这种模式通常用于在访问对象时引入额外的功能,而不改变对象的接口。代理模式的核心思想是为其他对象提供一种代理,以控制对这个对象的访问。在现实生活中,代理模......
  • 设计模式之责任链模式
    责任链模式是面向对象的23种设计模式中的一种,属于行为模式范围。责任链模式(ChainofResponsibility),见名知意:就是每一个处理请求的处理器组合成一个链表,链表中的每个节点(执行器)都有机会处理发送的请求。大致的结构是这个样子: 举一个简单的例子:某公司有一名新员工要入职,则入职......
  • Flannel Wireguard 模式
    FlannelWireGuard模式一、环境信息主机IPubuntu172.16.94.141软件版本docker26.1.4helmv3.15.0-rc.2kind0.18.0clab0.54.2kubernetes1.23.4ubuntuosUbuntu20.04.6LTSkernel5.11.5内核升级文档二、安装服务kind配置......
  • Flannel IPsec 模式
    FlannelIPSec模式一、环境信息主机IPubuntu172.16.94.141软件版本docker26.1.4helmv3.15.0-rc.2kind0.18.0clab0.54.2kubernetes1.23.4ubuntuosUbuntu20.04.6LTSkernel5.11.5内核升级文档二、安装服务kind配置文件......
  • 分布式事务的Seata AT模式原理
    Seata官网地址:https://seata.apache.org/zh-cn/AT模式优点:无侵入式代码,只需要添加注解,底层采用Seata代理的数据源DataSourceProxy缺点:依赖于数据库,目前只适用于postgresql、oracle、mysql、polardb-x、sqlserver、达梦数据库等数据库,比如业务逻辑中含有redis、es等操作需要控......