场景
当前有一套试题,总共有三道题目。现在小丽和亮亮要来答题。
- 2B铅笔的内芯是什么材质? a.铅 b.碳 c.石墨 答案:()
- 哪儿是世界上领土面积最大的国家? a.加拿大 b.俄罗斯 c.中国 d.德国 答案:()
- 谁是后世尊称的“药王”?a.僧一行 b.王叔和 c.李时珍 d.孙思邈 答案:()
第一版代码实现
public class LiliQuersionAnswer {
public void question1() {
System.out.println("1. 2B铅笔的内芯是什么材质? a.铅 b.碳 c.石墨");
System.out.println("答案:(C)");
}
public void question2() {
System.out.println("2. 哪儿是世界上领土面积最大的国家? a.加拿大 b.俄罗斯 c.中国 d.德国");
System.out.println("答案:(C)");
}
public void question3() {
System.out.println("3. 谁是后世尊称的“药王”?a.僧一行 b.王叔和 c.李时珍 d.孙思邈");
System.out.println("答案:(C)");
}
}
上版问题在哪儿?
所有人的卷面是一样的,但答案是不同人答题结果不一样。以上写法,问题无法复用;
注意:如果你想用question做接口,那么意味着你将有3个question接口实现类,对应的丽利和亮亮对应的answer需要没人三个实现的answer实现类。这个是过度设计的。
第二版代码
public abstract class AbstractQuestionAnswer {
public void question1(){
System.out.println("1. 2B铅笔的内芯是什么材质? a.铅 b.碳 c.石墨");
System.out.println("答案:(" + answer1()+")");
}
public void question2(){
System.out.println("2. 哪儿是世界上领土面积最大的国家? a.加拿大 b.俄罗斯 c.中国 d.德国");
System.out.println("答案:(" + answer2()+")");
}
public void question3() {
System.out.println("3. 谁是后世尊称的“药王”?a.僧一行 b.王叔和 c.李时珍 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";}
![template-method.png](http://upload-images.jianshu.io/upload_images/6379913-668f5e9f44124153.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
public String answer2() {return "c";}
public String answer3() {return "c";}
}
模板方法
概念
利用继承的方式,将公用的部分放入父类中,子类实现非公用(特殊)的部分。相当于基类(父类)定义算法骨架,并且将一些公用的实现放入基类中。子类实现基础类的定义,当然,可以覆盖基类的protected/public非abstract方法。
类图
场景
女娲带着小美女们造人了。造了三种人:白种人、黄种人、黑种人。人都有手臂、鼻子、眼睛、头、身体、腿,请用代码实现白种人、黄种人和黑种人
第一版代码(Version1)
public class WhitePersonBuilder {
public void build(){
System.out.println("我有一双深邃的眼睛");
System.out.println("我有一个高高的鼻梁");
System.out.println("我的皮肤很白");
System.out.println("我的手很长,手掌很大");
System.out.println("我的腿很长");
}
}
public class YellowPersonBuilder {
public void build(){
System.out.println("我有一双水灵的眼睛");
System.out.println("我有一个可爱的鼻梁");
System.out.println("我的皮肤是肉色");
System.out.println("我的手很细长,手掌有特点");
System.out.println("南边的腿是短的,北边的腿是长的");
}
}
第一版代码(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("我的手很长,手掌很大");
}
public void buildFoot(Person person) {
person.setFoot("我的腿很长");
}
public void buildEyes(Person person) {
person.setEyes("我有一双深邃的眼睛");
}
public void buildNose(Person person) {
person.setNose("我有一个高高的鼻梁");
}
}
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("---------------");
}
}
上版有问题吗?
version2的版本实现没有问题,相当于说你要给造个人,先给我个素材,然后按照模板方法做组装,有点像流水线上的汽车组装
第二版本代码
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("我的手长,只有掌心是白色的");
}
public void buildFoot() {
person.setFoot("我的腿全是黑毛,但是,你察觉不到");
}
public void buildEye() {
person.setEyes("我有一双深邃的眼睛");
}
public void buildNose() {
person.setNose("我有一个粗短的鼻梁");
}
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("---------------");
}
}
比较一下第二版实现和第一版(Version2)实现,有什么区别
- 第二版支持美女们在不动IBuilder的实现类的情况下造出残疾人(无foot或无hand),怎么呢实现呢?
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)实现残疾人必须重新定义abstractBuilder,并重新依据abstractBuilder实现子类,以支持残疾人的构造
建造者模式
概念
将一个复杂的构建与表示分离,使得同样的构建过程,能有不一样的表示。
类图
比较区别
- 建造者是使用组合方式实现不同的表示,而模板方法使用的是继承的方式。组合优于继承。
- 建造者抽象的是构建过程,而模板方法提取的是实现公共。