什麼是原型模式
什麼時候用到原型模式
原型模式有那些優缺點
oc與java文法上原型模式有那些異同及簡單的例子
java:Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.(用原型執行個體制定建立對象的種類,並且建立一個新的對象從原型對象拷貝而來。) iOS:用戶端知道抽象prototype類,在運行時,抽象Prototype子類的任何對象都可以按照用戶端的意願被複製,因此無需手工建立就可以製造同一個類型的多個執行個體。 根據兩者定義可以看出,原型模式就是,通過複製對象來建立新的執行個體。核心關鍵就是複製。 我們看一下iOS與Java原型模式的通用類圖: Java: iOS: 從他們的原型模式圖可以看出他們有一個關鍵的方法:clone-複製方法。從定義我們也不難得出原型模式就是對Prototpye對象的複製。
根據定義可以知道原型模式的核心就是clone或者copy,那為什麼我們不直接new一個對象或者alloc一個對象反而要通過複製來得到對象呢? 首先比較直觀的就建立起來比較麻煩,不是簡單的new或者alloc。我們先看一些書上的描述:
首先這些文字很繞口,先找比較好理解的解釋,需要要執行個體化的類是在運行時才決定,這個什麼意思呢,我的理解就是這個對象是一個組合對象,比如一個樹形結構的對象,不知道他具體的實現,也沒法建立,所以我copy一份。 不同執行個體之間差異僅是狀態的組合,這個也比較好理解,比如我畫一個小人頭,但是我需要很多小人頭他們只是顏色不一樣,黃中,白種,黑中,我不必把他們都重新畫一邊,我只需要畫出一個來,其他都複製於他,然後修改顏色就可以。 類不容易建立,這個就更好理解,我們建立一個類需要很多步驟,比如分配記憶體,然後載入資料,資料有來自資料庫等等,所以copy更節約資源。 不想要與產品層次相對應的工廠層次 與 需要建立的對象應獨立於其類型與建立方式 我的理解就是這樣情況用new或者alloc會很不合適比如一個程式有很多人蔘與一個程式員可能只負責編寫其中的一塊,當你嘗試編寫一個完全符合DIP的系統時,你可能無法避免要建立符合特定介面的新對象,但因為DIP原則不允許你依賴具體類型,完全無法決定要建立哪一個具體類,這個時候,原型模式提供了一個很討巧的辦法:“我要建立一個跟它類型一樣的對象!這個歡迎大家討論。
上面的描述中基本上都是原型模式的優點,他的缺點就是每個原型類都需要實現copy方法,如果類的某個對象不支援複製,那就會遇到很多麻煩。
首先他們都有一個關鍵點-複製,iOS裡面有深淺複製,當然java裡面也有 我們可以用一個共性的圖來表示一下 大體來說就是淺拷貝只是拷貝的指標,資源沒有複製,被拷貝的指標都指向同一塊記憶體地區,*p修改任何一個都會修改資源,深拷貝就是完全兩個對象,當然資源也被複製。 java中有的基類Object類中有一個clone方法,這個方法就是原型模式的關鍵。Java原型模式的通用源碼
public myclass clone()
{
Niuqhclass niuqh = null;
try {
niuqh = (Niuqhclass)super.clone();
}
catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return niuqh;
}
iOS的實現方式則主要是要實現NSCopying,重寫copyWithZone:的方法。 還是直接上例子:假如有一天易車網互連網排名世界第一了,需要在美英日三國分別成立一個公司,公司架構和現在的一樣,我們來看看java和iOS的兩種實現: java:
package MyClass;
/*
* 易車網類
* 只列舉了ceo和員工當然實際情況是一個樹形的結構比這要複雜的多
* 這個實現了 介面 Cloneable 重寫了 public clone()方法
* */
public class Yiche implements Cloneable {
public Yiche() {
}
ceo
private String ceo;
private String employee;
@Override
public Yiche clone()
{
Yiche yc = null;
try {
yc = (Yiche)super.clone();
}
catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return yc;
}
相關的set/get方法
public String getCeo(){
return ceo;
}
public void setCeo(String ceo){
this.ceo = ceo;
}
public String getEmployee()
{
return employee;
}
public void setEmployee(String employee){
this.employee = employee;
}
情境類
private static int MAX_COUNT =3;
public static void main(String[] args) {
int i = 0;
把易車模版定義出來
Yiche yc = new Yiche ();
yc.setCeo("李斌");(CEO只有一個)
while(i<MAX_COUNT)
Yiche cloneyc = yc.clone();(拷貝一個模版,添加員工)
yc.setEmployee("隨機人");(員工有很多不一樣的 人)
這樣就產生了三個子公司 可以派往 美國 英國 日本,這樣複製比重新編寫一個樹形的對象要簡單的多在看iOS中的實現 首先iOS裡面要先寫一個介面(協議protocol)IYiche他繼承了NSObject協議。這裡注意NSObject類和NSObject協議的區別以及為什麼蘋果這麼實現,這裡就不再講了。
#import <Foundation/Foundation.h>
@protocol IYiche <NSObject>
@property(nonatomic,retain)NSSting *ceo;
@property(nonatomic,retain)NSSting *employee;
-(id)copy;
@end
易車公司實現了協議IYiche
#import <Foundation/Foundation.h>
#import "IYiche.h"
@interface Yiche : NSObject<NSCopying,IYiche>
{
@protected
子公司自己的想要加的執行個體
}
@property(nonatomic,retain)NSSting *ceo;
@property(nonatomic,retain)NSSting *employee;
-(id)copyWithZone:(NSZone *)zone;
@end
這裡會有一個問題為什麼不是介面的中的copy方法而是 -(id)copyWithZone:(NSZone *)zone;方法,首先IYiche實現了NSCopying協議介面查看api在這個協議裡面是沒有copy方法的,這個方法在NSCopying類中,NSCopying類接受到copy訊息,會想採用了NSCopying協議的子類轉寄訊息,子類需要實現NSCopying協議中定義的-(id)copyWithZone:(NSZone *)zone;方法。NSCopying協議沒有copy方法所以才才讓IYiche聲明了。看一下此方法的實現 #pragma mark - #pragma mark NSCopying method //此方法需要實現,以支援備忘錄 -(id)copyWithZone:(NSZone *)zone { // 在這裡使用self class 是希望其子類也能返回和子類一樣的類型 Yiche *yichecopy = [[[self class]allocWithZone:zone]init]; return yichecopy; } 具體的情境類就不再寫了,主要是說明原型模式的簡單例子,再寫的時候也感覺到有一些不足,覺得能理解的東西在寫的時候也感覺不那麼敢確定,本文主要參考了Object-c編程之道,設計模式之蟬,COCOA設計模式。如果有理解不到位的地方希望大家提出自己的意見,給予改正。 請大家關注ios編程與大資料進行討論: |