原型模式_設計模式_java
技術標籤:設計模式
複製貼上功能我們都用過,我們可以把一個檔案從一個地方複製到另外一個地方,複製完成之後這個檔案和之前的檔案也沒有一點差別,這就是原型模式的思想:首先建立一個例項,然後通過這個例項去拷貝建立新的例項。這篇文章就好好地分析一下原型模式。
文章目錄
1.認識原型模式
1、概念
就比如克隆羊,用原型例項指定建立物件的種類,並通過拷貝這些原型建立新的物件。
java上分析:
首先我們可以看到一共有三個角色:
(1)客戶(Client)角色:客戶類提出建立物件的請求;也就是我們使用者使用複製貼上的功能。
(2)抽象原型(Prototype)角色:此角色定義了的具體原型類所需的實現的方法。也就是定義一個檔案,說明一下它有被克隆複製的功能。
(3)具體原型(Concrete Prototype)角色:實現抽象原型角色的克隆介面。就是我們的檔案實現了可以被複制的功能。
我們會發現其實原型模式的核心就是Prototype(抽象原型),他需要繼承Cloneable介面,並且重寫Object類中的clone方法才能有複製貼上的功能。
2.、分類
既然我們知道原型模式的核心就是拷貝物件,那麼我們能拷貝一個物件例項的什麼內容呢?這就要區分深拷貝和淺拷貝之分了。
(1)淺拷貝:我們只拷貝物件中的基本資料型別(8種),對於陣列、容器、引用物件等都不會拷貝
(2)深拷貝:不僅能拷貝基本資料型別,還能拷貝那些陣列、容器、引用物件等,
下面我們就使用程式碼去實現一下原型模式。這裡實現的是不僅有基本資料型別,還有陣列和容器,所以實現的是深拷貝。
2.程式碼實現原型模式
1.淺拷貝:
public class Sheep implements Cloneable{ private String name; private int age; private String color; public Sheep friend; public Sheep(String name, int age, String color) { this.age = age; this.name = name; this.color = color; } 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 String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]"; } @Override protected Object clone() { // TODO 自動生成的方法存根 Sheep sheep = null; try { sheep = (Sheep)super.clone(); }catch(Exception e){ System.out.println(e.getMessage()); } return sheep; } }
public class ClientDemo02 {
@Test
public void test1() {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep sheep2 = (Sheep)sheep.clone();
System.out.println(sheep == sheep2);
}
}
false
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", 1, "白色");
sheep.friend = new Sheep("jacy", 2, "黑色");
Sheep sheep2 = (Sheep)sheep.clone();
Sheep sheep3 = (Sheep)sheep.clone();
System.out.println(sheep.friend.hashCode());
System.out.println(sheep2.friend.hashCode());
System.out.println(sheep.friend == sheep2.friend);
}
}
2.深拷貝:
import java.io.Serializable;
public class DeepCloneableTarget implements Serializable,Cloneable{
private String className;
private String classClass;
private static final long serialVersionUID = 1L;
public DeepCloneableTarget(String className, String classClass) {
this.classClass = classClass;
this.className = className;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO 自動生成的方法存根
return super.clone();
}
}
import java.io.Serializable;
public class DeepProtoType implements Serializable,Cloneable{
public String name;
public DeepCloneableTarget deepCloneableTarget;
public DeepProtoType() {
}
//深拷貝實現
//1.重寫克隆方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
deep = super.clone();
DeepProtoType deepProtoType = (DeepProtoType)deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone();
// TODO 自動生成的方法存根
return deepProtoType;
}
//2.
}
public class Client {
public static void main(String[] args) throws Exception {
DeepProtoType deepProtoType = new DeepProtoType();
deepProtoType.name = "松江";
deepProtoType.deepCloneableTarget = new DeepCloneableTarget("大牛", "類");
//方式1.深拷貝
DeepProtoType p1 = (DeepProtoType)deepProtoType.clone();
System.out.println(deepProtoType.deepCloneableTarget == p1.deepCloneableTarget);
}
}
false
3.分析原型模式
對於原型模式有幾個問題需要我們去注意一下
1、克隆物件不會呼叫構造方法
從上面的輸出其實我們也可以發現,構造方法只在一開始我們建立原型的時候輸出了,fileB和fileC都沒有呼叫構造方法,這是因為執行clone方法的時候是直接從記憶體中去獲取資料的,在第一次建立物件的時候就會把資料在記憶體保留一份,克隆的時候直接呼叫就好了
2、訪問許可權對原型模式無效
原理也很簡單,我們是從記憶體中直接複製的,所以克隆起來也會直接無視,複製相應的內容就好了。
3、使用場景
(1)當我們的類初始化需要消耗很多的資源時,就可以使用原型模式,因為我們的克隆不會執行構造方法,避免了初始化佔有的時間和空間。
(2)一個物件被其她物件訪問,並且能夠修改時,訪問許可權都無效了,什麼都能修改。
OK,對於設計模式其實主要是理解其思想,然後根據自己的需求去靈活的使用。對於其他設計模式的相關文章也在持續更新當中。