原型模式(Prototype Pattern)
:用原型实例指定创建对象的种类,并且通过拷贝(克隆clone)这些原型创建新的对象。核心思想:通过克隆对象来隐藏对象的创建细节。
Cloneable
接口clone()
方法实现对象的克隆Prototype
:原型类
/**
* @create on 2020/8/23 16:16
* @description 原型类
* @author mrdonkey
*/
abstract class Prototype(var name: String, var list: ArrayList<String>) : Cloneable {
/**
* 提供克隆对象的方法
*/
abstract fun cloneObj(): Prototype
override fun toString(): String {
return "Prototype(name='$name',nameHashCode=${name.hashCode()}, list=$list , listHashCode=${list.hashCode()})"
}
}
ConcretePrototype1
:具体的原型类1
/**
* @create on 2020/8/23 16:17
* @description 具体原型类1
* @author mrdonkey
*/
class ConcretePrototype1(name: String, list: ArrayList<String>) : Prototype(name, list) {
override fun cloneObj(): Prototype {
return this.clone() as Prototype
}
}
Client
:客户端类
/**
* @create on 2020/8/23 16:17
* @description 客户端类
* @author mrdonkey
*/
class Client {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val obj = ConcretePrototype1("tom", arrayListOf("1", "2", "3"))
val cloneObj = obj.cloneObj()
//克隆对象修改name
println("----克隆对象修改name----")
cloneObj.name = "jeny"
println("obj-->$obj")
println("cloneObj-->$cloneObj")
//克隆对象更改list
println("----克隆对象更改list----")
cloneObj.list.add("4")
println("obj-->$obj")
println("cloneObj-->$cloneObj")
}
}
}
输出
----克隆对象修改name----
obj-->Prototype(name='tom',nameHashCode=115026, list=[1, 2, 3] , listHashCode=78481)
cloneObj-->Prototype(name='jeny',nameHashCode=3258438, list=[1, 2, 3] , listHashCode=78481)
----克隆对象更改list----
obj-->Prototype(name='tom',nameHashCode=115026, list=[1, 2, 3, 4] , listHashCode=2432963)
cloneObj-->Prototype(name='jeny',nameHashCode=3258438, list=[1, 2, 3, 4] , listHashCode=2432963)
在上面的程序输出中:我们可以看到被克隆后的对象cloneObj
改变name
不会影响原来的对象的name
,但是改变了list
则导致原来的list也发生了改变,这是由于系统自带的clone
方法只实现浅复制;需要实现对象深复制,则得重写clone
方法,并在方法中手动创建一个新的list
赋值给cloneObj
实现引用类型对象的赋值。注:String
是一种特殊的引用类型,修改就会新建一个string
实例,通过输出可以看出修改前后的hashCode
不同 。
这里指系统自带的clone方法的优缺点