目录
一、设计一个客户类Customer,其中客户地址存储在地址类Address中,用浅克隆和深克隆分别实现Customer对象的复制并比较这两种克隆方式的异同。绘制类图并编程实现。
二、使用单例模式的思想实现多例模式,确保系统中某个类的对象只能存在有限个,如两个或三个,设计并编写代码实现一个多例类。
这里对原型模式就不做详细介绍了,主要是单例模式。
原型模式:在创建一个对象的时候,直接从另外一个复制过来,用的不太多。
单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点(优点:1.对唯一实例的受控访问;2.单例相当于全局变量,但防止了命名空间被污染。)
单例模式示例:
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# @Time :
# @Author :
# @Version:V 0.1
# @File : 单例模式.py
# @desc : 保证一个类只有一个实例,并提供一个访问它的全局访问点
class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
class MyClass(Singleton):
def __init__(self, a):
self.a = a
a = MyClass(10)
b = MyClass(20)
print(a.a)
print(b.a)
print(id(a), id(b))
一、设计一个客户类Customer,其中客户地址存储在地址类Address中,用浅克隆和深克隆分别实现Customer对象的复制并比较这两种克隆方式的异同。绘制类图并编程实现。
通常情况下,一个类包含一些成员对象,在使用原型模式克隆对象时,根据其成员对象是否也克隆,原型模式可以分为两种形式:深克隆与浅克隆,下面分别使用这两种方式来实现Customer对象的复制。
1.1 浅克隆实现Customer对象复制:
在浅克隆中,被复制对象的所有普通成员变量都具有与原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象。类图与对应的Java代码如下:
图1 使用浅克隆实现Customer对象复制的模式结构图
为了获取对象的一份拷贝,我们可以利用Object类的clone()方法,步骤如下:(1)在派生类中覆盖基类的clone()方法,并声明为public;(2)在派生类的clone方法中,调用super.clone();(3)在派生类中实现Cloneable接口,具体代码实现如下(Java):
地址类(Address):
public class Address {
private String country;
private String province;
private String city;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Address(String country, String province, String city) {
super();
this.country = country;
this.province = province;
this.city = city;
}
@Override
public String toString() {
return "Address [city=" + city + ", country=" + country + ", p
rovince="
+ province + "]";
}
}
客户类(Customer):
public class Customer implements Cloneable{
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Customer(String name, Address address) {
super();
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "Customer [address=" + address + ", name=" + name + "]"
;
}
public Customer clone(){
Customer clone=null;
try {
clone=(Customer) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
测试类(Test):
package pagebaobaotql;
public class Test {
public static void main(String[] args) {
Address address=new Address("SC","CD","WHQ");
Customer c1=new Customer("sqq", address);
Customer c2=c1.clone();
c2.getAddress().setCity("MY");
System.out.println("c1"+c1.toString());
System.out.println("c2"+c2.toString());
}
}
1.2 深克隆实现Customer对象复制(Java)
在深克隆中被复制的对象的所有普通成员变量也都含有与原来的对象相同的值,出去那些引用其他对象的变量。换言之,在深克隆中,除了对象本身被复制外,对象包含的引用也被复制,也就是其中的成员对象也被复制。类图与对应的Java代码如下:
图2 使用深克隆实现Customer对象复制的模式结构图
1.针对Address类:
(1)在Address中重写clone()方法,并声明为public;
(2)在Address的clone方法中,调用super.clone();
(3)在Address中实现Cloneable接口;
2.针对Customer类:调用Address类的clone()方法修改为:
public Customer clone(){
Customer cus=null;
try {
cus=(Customer) super.clone();
cus.address=(Address) address.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cus;
}
序列化(Serialization)就是将对象写到流的过程,写到流中的对象是原有的对象的一个拷贝,而原对象仍存在内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且也可以复制其引用的成员对象,因此通过序列化将对象写入一个流中,再从流中将其读出来,从而实现深克隆。
客户类(Customer):
public class Customer implements Serializable{
private Address address;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Customer(String name, Address address) {
super();
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "Customer [address=" + address + ", name=" + name + "]";
}
public Object deepClone() throws Exception {
//将对象写入流中
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bao);
oos.writeObject(this);
//将对象从流中取出
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return(ois.readObject());
}
}
二、使用单例模式的思想实现多例模式,确保系统中某个类的对象只能存在有限个,如两个或三个,设计并编写代码实现一个多例类。
2.1使用单例模式实现多例模式结构图
图3 使用单例模式实现多例模式结构图
单例模式指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new构造函数( )”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例,代码如下。
import java.util.*;
public class Multiton {
//两个或者三个
private static ArrayList<Multiton> multitonList = new ArrayList<>();
private final static int NUMBER=3;
private Multiton(){
}
public static Multiton getInstance() {
// TODO: implement
if (multitonList.size()<NUMBER){
System.out.println("创建新实例成功");
Multiton current = new Multiton();
multitonList.add(current);
return current;
}else{
System.out.println("不能创建更多的实例");
return multitonList.get(new Random().nextInt(multitonList.size()));
}
}
}
客户端类:
public class Client {
public static void main(String[] args) {
Multiton m1 = Multiton.getInstance();
Multiton m2 = Multiton.getInstance();
Multiton m3 = Multiton.getInstance();
Multiton m4 = Multiton.getInstance();
System.out.println("m1==m2:"+(m1==m2));
System.out.println("m2==m3:"+(m2==m4));
System.out.println("m3==m4:"+(m3==m4));
}
}