簡介:
開閉原則
今天來說一下設計模式的6大原則之一的開閉原則。開閉原則是由勒蘭特·梅耶在1988年的著作《面向對象軟件構造》中首先提出的,其中提到了開閉原則的定義:對擴展開放,對修改關閉。即在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性好,易於維護和升級。
那麼開閉原則怎麼實現呢?可以通過“抽象約束、封裝變化”來實現開閉原則,即通過接口或者抽象類爲軟件實體定義一個相對穩定的抽象層,而將相同的可變因素封裝在相同的具體實現類中。
原型模式:
原型模式(Prototype Pattern)是用於創建重複的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
原型模式的運用場景一般分爲兩種:
- 防止自己的實例在傳入別的模塊後,發生意外的修改。進行一次拷貝,再將該實例傳遞給別的模塊,可以有效的避免意外的篡改,始終保持該實例的原始性。
- 爲了提高效率,很多時候我們需要大量的獲取一個對象相同的實例,通過原型模式“克隆”出一個內部屬性一樣的對象是個好的選擇,因爲類的初始化需要耗費很多的資源。
Android中的使用:
原型模式在android中有很多運用,如常見的Intent就實現了原型模式。
Intent intent = new Intent(PrototypeDesignActivity.this,BuilderDesignActivity.class);
Intent cloneIntent = (Intent) intent.clone();
那麼原型模式是如何實現的呢?首先需要對該類實現Cloneable接口,接着去重寫clone()方法,最後在clone()方法中實現類的拷貝。
public class Intent implements Parcelable, Cloneable {
......
@Override
public Object clone() {
return new Intent(this);
}
......
}
需要注意的是,重寫的clone()方法並不是Cloneable接口中的,因爲該接口是一個空接口。
/**
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
其實通過Cloneable接口的註釋我們也能知道clone()方法是來自於Object類。並告訴我們有關重寫此方法的詳細信息請參見Object.clone()方法。
/**
* @return a clone of this instance.
* @exception CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class " + getClass().getName() +
" doesn't implement Cloneable");
}
return internalClone();
}
內容很簡單,首先判斷是否實現了Cloneable接口,如果沒有實現就重寫此方法,最終會拋出CloneNotSupportedException異常。如果實現過這個類最終返回internalClone()方法。
/*
* Native helper method for cloning.
*/
private native Object internalClone();
最終我們可以看到這是一個native方法,用於輔助clone。
補充:
深拷貝與淺拷貝
我們知道java中分爲基本數據類型和引用數據類型,深淺拷貝就是針對引用數據類型所說的。舉個栗子:假如我們用對象A的clone()方法複製了對象B。這時候我們修改A中的某個引用數據類型的屬性,這個時候B也跟着改變了,那麼這種拷貝方式就是淺拷貝,如果B相對於A是獨立的對象,不受到A中任何屬性的影響,即A,B中相同的引用所指的地址不同,那麼這種就是深拷貝。
常用的實現深拷貝的方式有:遞歸、利用JSON轉換對象、利用Serializable或者Parcelable實現序列化來實現。