一、C++的浅拷贝与深拷贝对比Java的浅克隆与深克隆案例

C++部分

#include<iostream>
#include<string>
using namespace std;

class Email {
private:
	string title;
    /*这里是一个指针,当经行拷贝时,会产生另一个指针也指向它堆对应的地址。
      当用户删除原来的指针时,会把对象里面的这个指针也删除,那么此时,第二个指向里面的对象就会丢失对象中的int指针。
    */
	int* pNumber;
public:
	Email(string title) {
		this->title = title;
		this->pNumber = new int(666);
	}
	Email(const Email& email) {
		this->title = email.title;
		this->pNumber = email.pNumber;
	}
	~Email() {
		delete pNumber;
	}
};

int main() {
		Email e1("message");
		Email e2 = e1;
	return 0;
}

Java部分

import java.util.ArrayList;
import java.util.List;
public class Student implements Cloneable{//想要拷贝就得实现这个接口
    private String name;
    private int age;
    private String gender;
    private List<String> friends;

    public Student clone() throws CloneNotSupportedException{
            Student student=(Student) super.clone();
            List<String> new_friends=new ArrayList<String>();//在这里自己重新开辟一个新的对象,把新的对象赋给新cpoy的Students
            for(String friends:this.getFriends()){
                new_friends.add(friends);//把以前的list中的数据拷贝到新的friends中去
            }
            student.setFriends(new_friends);
            return student;//把加工后的student返回    
   	 }
	//set、get方法略

}
////////////////////////////////////////////////////////////////////////////
import java.util.ArrayList;
import java.util.List;
public class Main {
    public static void main(String[] args) {
        Student s1=new Student();
        /*Student s2=s1;
        System.out.println(s1==s2);//true,指向的是堆里面的同一个对象的地址*/

        //继承了Cloneable方法
        List<String> friends=new ArrayList<String>();
        friends.add("swift");
        friends.add("jack");
        s1.setFriends(friends);
        Student s2=s1.clone();//调用Java给的克隆方法实现克隆
        System.out.println(s1==s2);//false
        System.out.println(s1.getFriends());//[swift, jack]
        System.out.println(s2.getFriends());//[swift, jack]
        friends.add("newFriend");
        s1.setFriends(friends);//对s1更改,看s2是否变化
        System.out.println(s1.getFriends());
        System.out.println(s2.getFriends());//s2也变了,说明两个对象指向的是同一个friends对象

        //对clone方法更改后,发现s2没有变化了,说明他们两个student对象独立了
                /*false
                [swift, jack]
                [swift, jack]
                [swift, jack, newFriend]
                [swift, jack]*/
    }
}

二、建造者模式

1、建造者(Builder)模式的定义

是指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

2、模式的结构

建造者(Builder)模式的主要角色:

  1. 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。

  2. 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。

  3. 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。

  4. 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

3、 模式的实现

(1) 产品角色:包含多个组成部件的复杂对象。

//Actor类
public class Actor {
    private String type;
    private String sex;
    private String face;
    private String costume;
    private String hairstyle;
	
    //set.get方法略
}

(2) 抽象建造者:包含创建产品各个子部件的抽象方法。

//ActorBuilder 类
public abstract class ActorBuilder {
    Actor actor = new Actor();  //创建角色对象

    public abstract void BuildType();
    public abstract void BuildSex();
    public abstract void BuildFace();
    public abstract void BuildCostume();
    public abstract void BuildHairstyle();
    
	//返回角色对象
    public Actor CreateActor(){
         return actor;
    }
}

(3) 具体建造者:实现了抽象建造者接口。

//DevilBuilder类
public class DevilBuilder extends ActorBuilder{

    @Override
    public void BuildType() {
        this.actor.setType("恶魔");
    }

    @Override
    public void BuildSex() {
        this.actor.setSex("男");
    }
	// BuildFace()、BuildCostume()、BuildHairstyle()省略
    
    @Override
    public Actor CreateActor() {
        BuildType();BuildSex();BuildFace();BuildCostume();BuildHairstyle();
        return this.actor;
    }
////////////////////////////////////////
//AngelBuilder类
public class AngelBuilder extends ActorBuilder{
   //省略。。。
}

(4) 指挥者:调用建造者中的方法完成复杂对象的创建。

//ActorController类
public class ActorController {
    public Actor Construct(ActorBuilder ab){
        return ab.CreateActor();
    }
}

(5) 客户类。

// Client测试类
public class Client {
    public static void main(String[] args) {
        ActorController ac = new ActorController();
        ActorBuilder ab = new DevilBuilder();
        Actor actor = ac.Construct(ab);
        System.out.println(actor);
    }
}

4、建造者模式和工厂模式的区别

区别:

  • 建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
  • 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
  • 关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
  • 建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。

版权声明:本文为52yu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/52yu/p/14779200.html