当前位置 : 主页 > 大数据 > 区块链 >

原型模式(Prototype Pattern)

来源:互联网 收集:自由互联 发布时间:2021-06-22
原型模式定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 原型模式类图如下: 我们来看下下面的代码 public class Brand { private String name; private int age; public

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

原型模式类图如下:


我们来看下下面的代码


public class Brand {
    private String name;
    private int age;

    public Brand(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class Car {
    private int height;
    private int weight;
    private String country;
    private Brand brand;

    public Car(int height, int weight, String country, Brand brand){
        this.height = height;
        this.weight = weight;
        this.country = country;
        this.brand = brand;
    }

    public void getInfo(){
        System.out.println("height : " + height);
        System.out.println("weight : " + weight);
        System.out.println("country : " + country);
        System.out.println("brand name : " + brand.getName());
        System.out.println("brand age : " + brand.getAge());
    }
}
public class Buyer {

    public List<Car> buy(int num){
        List<Car> cars = new LinkedList<>();

        if(num == 1){
            Car car = new Car(2, 10, "Germany",
                    new Brand("Benz", 2018));
            cars.add(car);

        }else{
            Car car1 = new Car(2, 10, "Germany",
                    new Brand("Benz", 2018));
            cars.add(car1);
            Car car2 = new Car(2, 10, "Germany",
                    new Brand("Benz", 2018));
            cars.add(car2);
        }

        return cars;
    }
}

Car类的构造函数仅有4个参数,还不算特别多,如果Car类的构造函数有40个参数怎么办,每次实例化的时候都要传入40个参数实在是太麻烦

Java中提供了Cloneable接口,以便通过拷贝已有对象实例生成新的实例


public class Car implements Cloneable {
    private int height;
    private int weight;
    private String country;
    private Brand brand;

    public Car(int height, int weight, String country, Brand brand){
        this.height = height;
        this.weight = weight;
        this.country = country;
        this.brand = brand;
    }

    public void getInfo(){
        System.out.println("height : " + height);
        System.out.println("weight : " + weight);
        System.out.println("country : " + country);
        System.out.println("brand name : " + brand.getName());
        System.out.println("brand age : " + brand.getAge());
    }

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

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public Brand getBrand() {
        return brand;
    }

    public void setBrand(Brand brand) {
        this.brand = brand;
    }
}
public class Buyer {

    public List<Car> buy(int num) throws Exception {
        List<Car> cars = new LinkedList<>();

        if(num == 1){
            Car car = new Car(2, 10, "Germany",
                    new Brand("Benz", 2018));
            cars.add(car);

        }else{
            Car car1 = new Car(2, 10, "Germany",
                    new Brand("Benz", 2018));
            cars.add(car1);
            Car car2 = (Car)car1.clone();
            cars.add(car2);
        }

        return cars;
    }
}

使用测试类进行测试

public class Test {
    public static void main(String[] args) throws Exception {
        Buyer buyer = new Buyer();
        List<Car> cars = buyer.buy(2);
        cars.get(0).getBrand().setName("BMW");
        for(Car c : cars){
            System.out.println(c.getBrand().getName());
            System.out.println(c.getBrand().hashCode());
        }
    }
}

执行结果如下

BMW
1329552164
BMW
1329552164

从执行结果我们可以发现Object类提供的clone方法进行的是浅表复制,即:如果属性是基本类型,则进行值复制,如果属性是对象类型,则仅进行引用复制(我们常用的Apache的commons-beanutils提供的对象属性复制方法也是浅表复制)

protected native Object clone() throws CloneNotSupportedException;

Object类中的clone方法是native方法,会调用系统级别函数,所以执行速度会很快

如果我们想要进行深度复制,即:无论属性是基本类型还是对象类型,都进行对象复制,看下面的设计方式


public class Brand implements Cloneable {
    private String name;
    private int age;

    public Brand(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Car implements Cloneable {
    private int height;
    private int weight;
    private String country;
    private Brand brand;

    public Car(int height, int weight, String country, Brand brand){
        this.height = height;
        this.weight = weight;
        this.country = country;
        this.brand = brand;
    }

    public void getInfo(){
        System.out.println("height : " + height);
        System.out.println("weight : " + weight);
        System.out.println("country : " + country);
        System.out.println("brand name : " + brand.getName());
        System.out.println("brand age : " + brand.getAge());
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Car c = (Car)super.clone();
        if(brand != null){
            Brand b = (Brand)brand.clone();
            c.setBrand(b);
        }
        return c;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public Brand getBrand() {
        return brand;
    }

    public void setBrand(Brand brand) {
        this.brand = brand;
    }
}

再次测试结果如下

BMW
1329552164
Benz
363771819

在进行深度复制时,如果对象属性依然包含对象属性,则每一层都需要进行深度复制,复制的层数可能会失控,对性能会有严重影响

网友评论