原型模式
- 原型模式:用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過(guò)復(fù)制該原型對(duì)象來(lái)創(chuàng)建一個(gè)和原型對(duì)象相同的對(duì)象鼎姊;
- 原型模式的角色:
- 抽象原型類:規(guī)定了具體原型對(duì)象必須實(shí)現(xiàn)的clone()方法婆赠;
- 具體原型類:實(shí)現(xiàn)抽象原型類的clone()方法妙黍,它是可以被復(fù)制的對(duì)象做粤;
- UML類圖如下:
- 原型模式的克隆分為淺克隆與深克隆:
- 淺克缕隆:創(chuàng)建一個(gè)新對(duì)象阳距,新對(duì)象的屬性與原來(lái)對(duì)象完全相同,
- 深克乱ㄏ恰:創(chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆蜀撑,不再指向原有對(duì)象地址糊肤;
- 在Java中的Object類中提供了clone()方法來(lái)實(shí)現(xiàn)克隆拗踢,Cloneable接口就是抽象原型類叉庐,而實(shí)現(xiàn)了Cloneable接口的子類就是具體原型類兴溜;
- 代碼實(shí)現(xiàn)如下:
import androidx.annotation.NonNull;
public class Realizetype implements Cloneable{
public Realizetype() {
System.out.println("具體原型對(duì)象查創(chuàng)建成功");
}
@NonNull
@Override
public Realizetype clone() throws CloneNotSupportedException {
System.out.println("具體原型對(duì)象復(fù)制成功");
return (Realizetype) super.clone();
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sign.prototype.Realizetype;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Realizetype realizetype = new Realizetype();
try {
Realizetype clone = realizetype.clone();
System.out.println("原型與克隆是否是同一個(gè)對(duì)象" + (realizetype == clone));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
- 案例:三好學(xué)生的獎(jiǎng)狀穿稳,同一學(xué)校三好學(xué)生的獎(jiǎng)狀除了獲獎(jiǎng)人姓名不同央拖,其他都相同柏蘑,可以使用原型模式復(fù)制多個(gè)三好學(xué)生獎(jiǎng)狀,然后再修改獎(jiǎng)狀上的名字即可觉阅,UML類圖如下:
import androidx.annotation.NonNull;
public class Citation implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "同學(xué): 在2021年12月1日 獲取三號(hào)學(xué)生,特發(fā)此狀");
}
@NonNull
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sign.prototype.Citation;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Citation citation = new Citation();
try {
Citation c1 = citation.clone();
c1.setName("張三");
citation.setName("李四");
citation.show();
c1.show();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
- 使用場(chǎng)景:
- 對(duì)象創(chuàng)建非常復(fù)雜震檩,可使用原型模式快捷創(chuàng)建對(duì)象沸毁;
- 性能和安全要求比較高的;
擴(kuò)展(深克隆)
- 將三好學(xué)生獎(jiǎng)狀類
Citation
的name 屬性 修改為Student 類型的屬性呀潭,代碼如下:
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import androidx.annotation.NonNull;
public class Citation implements Cloneable{
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public void show() {
System.out.println(student.getName() + "同學(xué): 在2021年12月1日 獲取三號(hào)學(xué)生身害,特發(fā)此狀");
}
@NonNull
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sign.prototype.Citation;
import com.example.sign.prototype.Student;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Citation citation = new Citation();
Student student = new Student();
student.setName("張三");
citation.setStudent(student);
try {
Citation c1 = citation.clone();
c1.getStudent().setName("李四");
citation.show(); //李四
c1.show(); //李四
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
-
citation
與c1
指向同一個(gè)對(duì)象;
- 下面通過(guò)
序列化技術(shù)
,實(shí)現(xiàn)對(duì)象的深克隆抢埋,代碼如下:
import java.io.Serializable;
public class Student implements Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import androidx.annotation.NonNull;
import java.io.Serializable;
public class Citation implements Cloneable, Serializable {
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public void show() {
System.out.println(student.getName() + "同學(xué): 在2021年12月1日 獲取三號(hào)學(xué)生,特發(fā)此狀");
}
@NonNull
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sign.prototype.Citation;
import com.example.sign.prototype.Student;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Citation citation = new Citation();
Student student = new Student();
student.setName("張三");
citation.setStudent(student);
//創(chuàng)建輸出流
try {
//將對(duì)象序列化到磁盤文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("User/liyanyan/desktop/a.txt"));
//寫對(duì)象
oos.writeObject(citation);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("User/liyanyan/desktop/a.txt"));
Citation citation1 = (Citation) ois.readObject();
ois.close();
Student student1 = citation1.getStudent();
student1.setName("李四");
citation.show(); //張三
citation1.show(); //李四
} catch (Exception e) {
e.printStackTrace();
}
}
}
-
citation
與citation1
指向的是兩個(gè)不同的對(duì)象戏自,其中Citation類與Student類都必須實(shí)現(xiàn)Serializable
接口和二;
- 上述的淺克隆徘铝,深克隆與iOS中淺拷貝,深拷貝的原理是相同的惯吕;
建造者模式
- 建造者模式:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與表示分離惕它,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示;
- 實(shí)現(xiàn)了構(gòu)建與裝配的解耦废登,不同的構(gòu)建器淹魄,相同的裝配,可作出不同的對(duì)象堡距,相同的構(gòu)建器甲锡,不同的裝配順序也可作出不同的對(duì)象,也就實(shí)現(xiàn)了構(gòu)建算法與裝配算法之間的解耦羽戒,實(shí)現(xiàn)了更好的復(fù)用缤沦;
- 建造者模式可以將部件與其組裝過(guò)程分開(kāi),一步一步創(chuàng)建一個(gè)復(fù)雜對(duì)象易稠,客戶只需要指定復(fù)雜對(duì)象的類型就可以得到該對(duì)象缸废,而無(wú)需知道其內(nèi)部的具體構(gòu)造細(xì)節(jié);
- 建造者模式中的角色:
- 抽象建造者類(Builder):定義了復(fù)雜對(duì)象各部件創(chuàng)建的接口驶社;
- 具體建造者類:實(shí)現(xiàn)了Builder中的接口企量,完成部件的創(chuàng)建,在構(gòu)造完成之后亡电,返回產(chǎn)品實(shí)例届巩;
- 產(chǎn)品類:需要的創(chuàng)建的復(fù)雜對(duì)象;
- 指揮者類(Director):調(diào)用具體建造者來(lái)創(chuàng)建復(fù)雜對(duì)象的各個(gè)部分份乒,在指揮者類中恕汇,不涉及具體產(chǎn)品信息,只負(fù)責(zé)保證對(duì)象各部分完整創(chuàng)建或按某種順序創(chuàng)建或辖;
- 下面以創(chuàng)建自行車為案例拇勃,來(lái)闡述建造者模式,首先產(chǎn)品類是自行車這個(gè)復(fù)雜對(duì)象孝凌,其包含車架與車座,車架有碳纖維月腋,鋁合金蟀架,車座有真皮瓣赂,橡膠,UML類圖如下所示:
public class Bike {
private String frame;
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
//抽象建造者
public abstract class Builder {
protected Bike bike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
}
public class MobleBuilder extends Builder{
@Override
public void buildFrame() {
bike.setFrame("碳纖維車架");
}
@Override
public void buildSeat() {
bike.setSeat("真皮車座");
}
@Override
public Bike createBike() {
return bike;
}
}
public class OfoBuilder extends Builder{
@Override
public void buildFrame() {
bike.setFrame("鋁合金車架");
}
@Override
public void buildSeat() {
bike.setSeat("橡膠車座");
}
@Override
public Bike createBike() {
return bike;
}
}
//指揮者類 裝配
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Bike construct() {
builder.buildFrame();
builder.buildSeat();
return builder.bike;
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.example.sign.build.Bike;
import com.example.sign.build.Director;
import com.example.sign.build.MobleBuilder;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Director director = new Director(new MobleBuilder());
Bike bike = director.construct();
System.out.println(bike.getFrame() + bike.getSeat());
}
}
- 上述案例是Builder模式的常規(guī)用法片拍,指揮者Director在建造者模式中具有很重要的作用煌集,它用于指導(dǎo)具體構(gòu)建者如何構(gòu)建產(chǎn)品,控制先后次序捌省,并向調(diào)用者返回完整的產(chǎn)品類苫纤,可以考慮將指揮者Director與抽象建造者類Builder進(jìn)行合并,代碼如下:
//抽象建造者
public abstract class Builder {
protected Bike bike = new Bike();
public abstract void buildFrame();
public abstract void buildSeat();
public abstract Bike createBike();
public Bike construct() {
this.buildFrame();
this.buildSeat();
return this.createBike();
}
}
- 這樣設(shè)計(jì)簡(jiǎn)化了系統(tǒng)結(jié)構(gòu)纲缓,但加重了抽象建造者Builder的職責(zé)卷拘,若指揮者Director類邏輯過(guò)于復(fù)雜,建議還是將兩者分開(kāi)祝高;