Prototype 模式:
- 當對象種類繁多的時候,我們可以把它們合併到一個類中去。
- 難以根據類生成實例的時候。
- 想解耦框架和生成的實例時,使生成框架不依賴於任何類。
- 當一個實例進行了很多操作,比如關於字段的存入,一些方法對於類內字段的處理時,如果我們想要對實例進行復用,我們就可以考慮使用這種模式,我們不僅將實例複製了,省去了很多操作,而且實例之間雖然字段相同,但是已經是兩個實例,操作互不影響,也就是直接clone一個實例來用,爲了解耦不去幹擾已經用過這個實例的操作。
實例:
- Sport 類表示運動的接口,需要繼承Cloneable 接口,以及Football,Basketball兩個類來表示足球和籃球,以及需要實現的方法時howToPlay,getBestPlayer。
- 我們可以使用Manager類來返回複製後的Football,Basketball,比如Manager類中的setSport方法,我們會要求存儲關於這項運動男子的最佳運動員的名字,現在我們不太需要變更最佳運動員以及怎麼進行運動的信息,這個時候我們可以使用一次存入,多次clone。
Sport 接口:
package com.zyy.pattern.service;
public interface Sport extends Cloneable{
public String howToPlay();
public String getBestPlayer();
public void showMessage();
public Sport cloneSport();
}
Football 類:
package com.zyy.pattern.beans;
import static org.hamcrest.CoreMatchers.nullValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zyy.pattern.service.Sport;
public class Football implements Sport{
private Logger logger = LoggerFactory.getLogger(Football.class);
private String bestPlayerName;
public Football(String bestPlayerName) {
this.bestPlayerName = bestPlayerName;
}
@Override
public String howToPlay() {
return "you can play with a ball by your foot";
}
@Override
public String getBestPlayer() {
return bestPlayerName;
}
@Override
public void showMessage() {
logger.info("how tot play : {} , the best player : {}",howToPlay(),getBestPlayer());
}
@Override
public Sport cloneSport() {
Sport sport = null;
try {
sport = (Sport) clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sport;
}
}
Basketball 類:
package com.zyy.pattern.beans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zyy.pattern.service.Sport;
public class Basketball implements Sport{
private Logger logger = LoggerFactory.getLogger(Basketball.class);
private String bestPlayerName;
public Basketball(String bestPlayerName) {
this.bestPlayerName = bestPlayerName;
}
@Override
public String howToPlay() {
return "you can play with a ball by your hand";
}
@Override
public String getBestPlayer() {
return bestPlayerName;
}
@Override
public void showMessage() {
logger.info("how tot play : {} , the best player : {}",howToPlay(),getBestPlayer());
}
@Override
public Sport cloneSport() {
Sport sport = null;
try {
sport = (Sport) clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sport;
}
}
Manager 類:
package com.zyy.pattern.beans;
import java.util.HashMap;
import com.zyy.pattern.service.Sport;
public class Manager {
private HashMap<String, Sport> managerMap = new HashMap<>();
public void register(String name,Sport sport) {
managerMap.put(name, sport);
}
public Sport create(String name) {
return managerMap.get(name).cloneSport();
}
}
測試用例以及測試結果:
public void prototypePatternTest() {
Basketball basketball = new Basketball("LeBron James");
Football football = new Football("Lionel Messi");
Manager manager = new Manager();
manager.register("basketball", basketball);
manager.register("football", football);
Sport sportFirst = manager.create("basketball");
Sport sportSecond = manager.create("basketball");
Sport sportThird = manager.create("football");
Sport sportForth = manager.create("football");
sportFirst.showMessage();
sportSecond.showMessage();
sportThird.showMessage();
sportForth.showMessage();
logger.info("basketball == : {}",sportFirst == sportSecond);
logger.info("football == : {}",sportThird == sportForth);
}
21:20:42.915 [main] INFO com.zyy.pattern.beans.Basketball - how tot play : you can play with a ball by your hand , the best player : LeBron James
21:20:42.918 [main] INFO com.zyy.pattern.beans.Basketball - how tot play : you can play with a ball by your hand , the best player : LeBron James
21:20:42.918 [main] INFO com.zyy.pattern.beans.Football - how tot play : you can play with a ball by your foot , the best player : Lionel Messi
21:20:42.918 [main] INFO com.zyy.pattern.beans.Football - how tot play : you can play with a ball by your foot , the best player : Lionel Messi
21:20:42.918 [main] INFO testSpringFirst.DesignPatternTest - basketball == : false
21:20:42.918 [main] INFO testSpringFirst.DesignPatternTest - football == : false
Cloneable 接口:
- 這是一個標記接口,它並沒有聲明任何方法,實現clone方法的是Object類,這個接口的存在只是判定能不能使用clone()這個方法。
- clone()只是淺複製,只是複製了字段而已。