場(chǎng)景
當(dāng)前有一套試題,總共有三道題目。現(xiàn)在小麗和亮亮要來(lái)答題。
- 2B鉛筆的內(nèi)芯是什么材質(zhì)? a.鉛 b.碳 c.石墨 答案:()
- 哪兒是世界上領(lǐng)土面積最大的國(guó)家? a.加拿大 b.俄羅斯 c.中國(guó) d.德國(guó) 答案:()
- 誰(shuí)是后世尊稱的“藥王”?a.僧一行 b.王叔和 c.李時(shí)珍 d.孫思邈 答案:()
第一版代碼實(shí)現(xiàn)
public class LiliQuersionAnswer {
public void question1() {
System.out.println("1. 2B鉛筆的內(nèi)芯是什么材質(zhì)? a.鉛 b.碳 c.石墨");
System.out.println("答案:(C)");
}
public void question2() {
System.out.println("2. 哪兒是世界上領(lǐng)土面積最大的國(guó)家? a.加拿大 b.俄羅斯 c.中國(guó) d.德國(guó)");
System.out.println("答案:(C)");
}
public void question3() {
System.out.println("3. 誰(shuí)是后世尊稱的“藥王”?a.僧一行 b.王叔和 c.李時(shí)珍 d.孫思邈");
System.out.println("答案:(C)");
}
}
上版問(wèn)題在哪兒?
所有人的卷面是一樣的,但答案是不同人答題結(jié)果不一樣。以上寫法,問(wèn)題無(wú)法復(fù)用;
注意:如果你想用question做接口,那么意味著你將有3個(gè)question接口實(shí)現(xiàn)類,對(duì)應(yīng)的麗利和亮亮對(duì)應(yīng)的answer需要沒(méi)人三個(gè)實(shí)現(xiàn)的answer實(shí)現(xiàn)類。這個(gè)是過(guò)度設(shè)計(jì)的。
第二版代碼
public abstract class AbstractQuestionAnswer {
public void question1(){
System.out.println("1. 2B鉛筆的內(nèi)芯是什么材質(zhì)? a.鉛 b.碳 c.石墨");
System.out.println("答案:(" + answer1()+")");
}
public void question2(){
System.out.println("2. 哪兒是世界上領(lǐng)土面積最大的國(guó)家? a.加拿大 b.俄羅斯 c.中國(guó) d.德國(guó)");
System.out.println("答案:(" + answer2()+")");
}
public void question3() {
System.out.println("3. 誰(shuí)是后世尊稱的“藥王”?a.僧一行 b.王叔和 c.李時(shí)珍 d.孫思邈");
System.out.println("答案:(" + answer3()+")");
}
public abstract String answer1();
public abstract String answer2();
public abstract String answer3();
}
public class DefaultQuestionAnswer extends AbstractQuestionAnswer {
public String answer1() {return "";}
public String answer2() {return "";}
public String answer3() {return "";}
}
public class PersonLiliQuestionAnswer extends DefaultQuestionAnswer {
public String answer1() {return "c";}

public String answer2() {return "c";}
public String answer3() {return "c";}
}
模板方法
概念
利用繼承的方式,將公用的部分放入父類中,子類實(shí)現(xiàn)非公用(特殊)的部分。相當(dāng)于基類(父類)定義算法骨架,并且將一些公用的實(shí)現(xiàn)放入基類中。子類實(shí)現(xiàn)基礎(chǔ)類的定義,當(dāng)然,可以覆蓋基類的protected/public非abstract方法。
類圖

template-method.png
場(chǎng)景
女媧帶著小美女們?cè)烊肆?。造了三種人:白種人、黃種人、黑種人。人都有手臂、鼻子、眼睛、頭、身體、腿,請(qǐng)用代碼實(shí)現(xiàn)白種人、黃種人和黑種人
第一版代碼(Version1)
public class WhitePersonBuilder {
public void build(){
System.out.println("我有一雙深邃的眼睛");
System.out.println("我有一個(gè)高高的鼻梁");
System.out.println("我的皮膚很白");
System.out.println("我的手很長(zhǎng),手掌很大");
System.out.println("我的腿很長(zhǎng)");
}
}
public class YellowPersonBuilder {
public void build(){
System.out.println("我有一雙水靈的眼睛");
System.out.println("我有一個(gè)可愛(ài)的鼻梁");
System.out.println("我的皮膚是肉色");
System.out.println("我的手很細(xì)長(zhǎng),手掌有特點(diǎn)");
System.out.println("南邊的腿是短的,北邊的腿是長(zhǎng)的");
}
}
第一版代碼(Version2)
public abstract class AbstractBuilder {
public void build(Person person) {
buildEyes(person);
buildNose(person);
buildHead(person);
buildHand(person);
buildFoot(person);
}
protected abstract void buildNose(Person person);
protected abstract void buildEyes(Person person);
protected abstract void buildHead(Person person);
protected abstract void buildHand(Person person);
protected abstract void buildFoot(Person person);
}
public class WhitePersonBuilder extends AbstractBuilder {
public void buildHead(Person person) {
person.setHead("我的皮膚很白");
}
public void buildHand(Person person) {
person.setHand("我的手很長(zhǎng),手掌很大");
}
public void buildFoot(Person person) {
person.setFoot("我的腿很長(zhǎng)");
}
public void buildEyes(Person person) {
person.setEyes("我有一雙深邃的眼睛");
}
public void buildNose(Person person) {
person.setNose("我有一個(gè)高高的鼻梁");
}
}
public class Test {
public static void main(String[] args){
Person whitePerson = new Person();
Person yellowPerson = new Person();
Person blackPerson = new Person();
AbstractBuilder whiteBuilder = new WhitePersonBuilder();
AbstractBuilder yellowBuilder = new YellowPersonBuilder();
AbstractBuilder blackBuilder = new BlackPersonBuilder();
whiteBuilder.build(whitePerson);
yellowBuilder.build(yellowPerson);
blackBuilder.build(blackPerson);
printPerson(whitePerson);
printPerson(yellowPerson);
printPerson(blackPerson);
}
private static void printPerson(Person blackPerson) {
System.out.println("eyes:"+blackPerson.getEyes());
System.out.println("nose:"+blackPerson.getNose());
System.out.println("head:"+blackPerson.getHead());
System.out.println("hand:"+blackPerson.getHand());
System.out.println("foot:"+blackPerson.getFoot());
System.out.println("---------------");
}
}
上版有問(wèn)題嗎?
version2的版本實(shí)現(xiàn)沒(méi)有問(wèn)題,相當(dāng)于說(shuō)你要給造個(gè)人,先給我個(gè)素材,然后按照模板方法做組裝,有點(diǎn)像流水線上的汽車組裝
第二版本代碼
public interface IPersonBuilder {
public void buildHead();
public void buildHand();
public void buildFoot();
public void buildEye();
public void buildNose();
public Person getResult();
}
public class BlackPersonBuilder implements IPersonBuilder {
private Person person = new Person();
public void buildHead() {
person.setHead("我的皮膚很黑");
}
public void buildHand() {
person.setHand("我的手長(zhǎng),只有掌心是白色的");
}
public void buildFoot() {
person.setFoot("我的腿全是黑毛,但是,你察覺(jué)不到");
}
public void buildEye() {
person.setEyes("我有一雙深邃的眼睛");
}
public void buildNose() {
person.setNose("我有一個(gè)粗短的鼻梁");
}
public Person getResult() {
return person;
}
}
public class Director {
public void constructor(IPersonBuilder personBuilder){
personBuilder.buildHead();
personBuilder.buildEye();
personBuilder.buildNose();
personBuilder.buildHand();
personBuilder.buildFoot();
}
}
public class Test {
public static void main(String[] args){
IPersonBuilder whitePersonBuilder = new WhitePersonBuilder();
IPersonBuilder yellowPersonBuilder = new YellowPersonBuilder();
IPersonBuilder blackPersonBuilder = new BlackPersonBuilder();
Director director = new Director();
director.constructor(whitePersonBuilder);
director.constructor(yellowPersonBuilder);
director.constructor(blackPersonBuilder);
Person whitePerson = whitePersonBuilder.getResult();
Person yellowPerson = yellowPersonBuilder.getResult();
Person blackPerson = blackPersonBuilder.getResult();
printPerson(whitePerson);
printPerson(yellowPerson);
printPerson(blackPerson);
}
private static void printPerson(Person blackPerson) {
System.out.println("eyes:"+blackPerson.getEyes());
System.out.println("nose:"+blackPerson.getNose());
System.out.println("head:"+blackPerson.getHead());
System.out.println("hand:"+blackPerson.getHand());
System.out.println("foot:"+blackPerson.getFoot());
System.out.println("---------------");
}
}
比較一下第二版實(shí)現(xiàn)和第一版(Version2)實(shí)現(xiàn),有什么區(qū)別
- 第二版支持美女們?cè)诓粍?dòng)IBuilder的實(shí)現(xiàn)類的情況下造出殘疾人(無(wú)foot或無(wú)hand),怎么呢實(shí)現(xiàn)呢?
public class DisableDirector {
public void constructor(IPersonBuilder personBuilder){
personBuilder.buildHead();
personBuilder.buildEye();
personBuilder.buildNose();
// personBuilder.buildHand();
// personBuilder.buildFoot();
}
}
public class Test {
public static void main(String[] args){
IPersonBuilder whitePersonBuilder = new WhitePersonBuilder();
IPersonBuilder yellowPersonBuilder = new YellowPersonBuilder();
IPersonBuilder blackPersonBuilder = new BlackPersonBuilder();
//殘疾人組裝類
Director director = new DisableDirector();
director.constructor(whitePersonBuilder);
director.constructor(yellowPersonBuilder);
director.constructor(blackPersonBuilder);
Person whitePerson = whitePersonBuilder.getResult();
Person yellowPerson = yellowPersonBuilder.getResult();
Person blackPerson = blackPersonBuilder.getResult();
printPerson(whitePerson);
printPerson(yellowPerson);
printPerson(blackPerson);
}
private static void printPerson(Person blackPerson) {
System.out.println("eyes:"+blackPerson.getEyes());
System.out.println("nose:"+blackPerson.getNose());
System.out.println("head:"+blackPerson.getHead());
System.out.println("hand:"+blackPerson.getHand());
System.out.println("foot:"+blackPerson.getFoot());
System.out.println("---------------");
}
}
- 第一版(version2)實(shí)現(xiàn)殘疾人必須重新定義abstractBuilder,并重新依據(jù)abstractBuilder實(shí)現(xiàn)子類,以支持殘疾人的構(gòu)造
建造者模式
概念
將一個(gè)復(fù)雜的構(gòu)建與表示分離,使得同樣的構(gòu)建過(guò)程,能有不一樣的表示。
類圖

屏幕快照 2017-06-09 下午9.58.40.png
比較區(qū)別
- 建造者是使用組合方式實(shí)現(xiàn)不同的表示,而模板方法使用的是繼承的方式。組合優(yōu)于繼承。
- 建造者抽象的是構(gòu)建過(guò)程,而模板方法提取的是實(shí)現(xiàn)公共。