第四章:对象创建型模式之原型模式

1.什么是原型模式?

原型模式是指通过原型实例指定要创建对象的类型,并通过拷贝原型实例创建新对象。原型模式之创建型设计模式,它提供一种创建对象的最佳实践。拷贝即clone(克隆),分为浅拷贝深拷贝两种。

浅拷贝:创建一个对象,新对象的属性和原对象完全相同,对于非基本类型对象,新对象的数据的引用仍指向原对象的属性引用指向的内存地址。简单来说,浅拷贝只克隆原对象本身和其包含的非引用类型属性,引用类型属性克隆。

深拷贝:创建一个对象,新对象的属性也会被拷贝,不在指向原有的对象地址。也就说通过深拷贝克隆的对象和原型对象完全独立开来,互补影响。

2.为什么使用原型模式?

1.当创建对象的过程较为复制且比较耗时时,使用原型对象可以高效的创建对象。

2.原型模式允许动态添加和删除新类型对象,而无需更改现有代码,提高了系统的可扩展性。

3.什么场景下适合使用原型模式?

1.当系统需要独立的它的产品创建,构成和表示时。

2.当需要实例化的类型需要在程序运行期间指定时。

3.当一个类的实例只能是几个状态的组合时,建立相同数量的原型并在每次需要时克隆他们,比每次根据状态实例化它来得方便。

4.和工厂模式结合使用,在实际项目中原型模式很少单独使用,一般是使用原型模式克隆对象后,有工厂模式返回给调用者使用。

4.哪些框架使用了原型模式?

1.Spring Framework ,在spring框架中当bean的作用于被设置为prototype时,每次请求都会创建一个新的bean实例,而不是从容器中获取bean实例。

2.Apache Common Lang这个库提供了SerializableUtils类,它使用原型模式克隆试下了Serializable接口的对象,它允许开发者通过序列化或反序列化创建对象的副本。

3.java集合框架中,clone()方法也是原型模式的引用,它允许开发者快发创建集合的副本,避免逐个添加元素。

5.怎么使用原型模式?

1.定义抽象原型接口,规定具体原型类必须实现的接口

在Java中,我们可以通过实现Cloneable接口,并重写clone()方法来实现原型模式,Cloneable是一个标记方法,实现它的类,表示该类的实例对象可以被复制,如果没实现Cloneable接口而直接调用clone()方法,程序会抛出CloneNotSupportedException异常。当然我们也可实现自己的抽象原型接口。

//定义抽象原型接口<形状>,并实现Cloneable接口,表示可以被克隆
public abstract class Shape implements Cloneable {
    private String id;
    private String type;
    private List<Integer> coordinates;
    abstract void draw();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public List<Integer> getCoordinates() {
        return coordinates;
    }

    public void setCoordinates(ArrayList<Integer> coordinates) {
        this.coordinates = coordinates;
    }

    @Override
    protected Shape clone()  {
        Shape shape = null;
        try {
            shape = (Shape) super.clone();
            //如果要进行深拷贝,需要手动拷贝每个引用类型属性
            shape.coordinates = (List<Integer>) ((ArrayList<Integer>) this.coordinates).clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return shape;
    }
}

2.定义具体原型类,实现抽象原型接口,表示原型类的实例是可以被clone的

//定义具体原型类<圆形>
public class Circle extends Shape {
    public Circle() {
        type = "圆形";
    }

    @Override
    void draw() {
        System.out.println("绘制圆形");
    }
}

/定义具体原型类<矩形>
public class Rectangle extends Shape {

    public Rectangle() {
        type = "矩形";
    }

    @Override
    void draw() {
        System.out.println("绘制矩形...");
    }
}

3.创建用户被克隆原型实例,并保存到缓存中,方便克隆

public class ShapeCache {
    //缓存原型对象
    private static final HashMap<String, Shape> shapeMap = new HashMap<>();
    //从缓存中取出原型对象克隆创建新对象并返回
    public static final Shape getShape(String shapeId) {
        Shape shape = shapeMap.get(shapeId);
        return shape.clone();
    }
    //加载原型对象。实际项目中,该对象可以从数据库获取,并在使用之前提前缓存好
    public static void loadCache() {
        Shape circle = new Circle();
        circle.setId("1");
        List<Integer> circleCoordinates = new ArrayList<>();
        circleCoordinates.add(1);
        circleCoordinates.add(2);
        circleCoordinates.add(10);
        circle.setCoordinates(circleCoordinates);
        shapeMap.put(circle.getId(), circle);

        Shape rectangle = new Rectangle();
        rectangle.setId("2");
        List<Integer> rectangleCoordinates = new ArrayList<>();
        rectangleCoordinates.add(1);
        rectangleCoordinates.add(2);
        rectangleCoordinates.add(10);
        rectangleCoordinates.add(12);
        rectangle.setCoordinates(rectangleCoordinates);
        shapeMap.put(rectangle.getId(), rectangle);
    }
}

4.客户端使用具体原型类中clone方法克隆创建对象

public class PrototypeClient {

    public static void main(String[] args) {
        //加载原型实例
        ShapeCache.loadCache();

        //克隆一个圆形对象
        Shape circle = ShapeCache.getShape("1");

        //克隆两个矩形对象
        Shape rectangle1 = ShapeCache.getShape("2");
        Shape rectangle2 = ShapeCache.getShape("2");

        System.out.println("圆形:" + circle.getType());
        System.out.println("矩形1:" + rectangle1.getType());
        System.out.println("矩形2:" + rectangle2.getType());
        System.out.println("矩形1==矩形2:" + (rectangle1 == rectangle2));
        System.out.println("矩形1组标==矩形2坐标:" + (rectangle1.getCoordinates() == rectangle2.getCoordinates()));
    }
}

运行结果如下:

6.原型模式符合哪些软件设计原则?

1.单一职责原则

原型模式通过提供一个原型实例来创建对象,调用者只需要关注如果使用这个克隆对象,而不必关心对象创建逻辑,这样将对象的创建和使用分离,使每个类的职责更加单一。

2.开放封闭原则

原型模式允许在不修改已有代码的情况下引入新类型的,通过克隆创建对象。可以使系统在运行时动态的添加和删除新类型的对象,提高了系统的可扩展性。

3.依赖倒转原则

调用者依赖抽象的原型接口,而不依赖具体原型类。使得系统更加灵活,更易维护。

4.合成复用原则

原型模式通过克隆已有的对象创建新对象,这是一种合成的方式,可以有效利用系统已有资源。

  • 38
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
原型模式是一种创建对象的设计模式,通过复制一个已有的对象创建新的对象。在JavaScript中,可以使用原对象创建LambdaQueryWrapper对象。 首先,你可以通过定义一个LambdaQueryWrapper对象的原对象,来指明所有创建的LambdaQueryWrapper对象的类。这个原对象包含LambdaQueryWrapper对象的属性和方法。 然后,可以使用原对象的复制方法,例如浅拷贝或深拷贝,来创建新的LambdaQueryWrapper对象。浅拷贝会复制原对象的引用,而深拷贝会复制原对象的属性和方法。 使用原型模式创建LambdaQueryWrapper对象的步骤如下: 1. 定义一个LambdaQueryWrapper对象的原对象,包含该对象的属性和方法。 2. 使用浅拷贝或深拷贝的方式,复制原对象创建新的LambdaQueryWrapper对象。 3. 对新创建的LambdaQueryWrapper对象进行进一步的配置和使用。 总之,原型模式是一种创建对象的方式,可以用于创建LambdaQueryWrapper对象。通过定义原对象并复制它来创建新的对象,可以快速创建相同类的LambdaQueryWrapper对象,并进行配置和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JS原对象创建方法详解](https://download.csdn.net/download/weixin_38585666/13003862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Java设计原则和设计模式](https://blog.csdn.net/sinat_34814635/article/details/115290417)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nick-weixizheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值