设计模式系列:模板方法模式和建造者模式

场景

当前有一套试题,总共有三道题目。现在小丽和亮亮要来答题。

  1. 2B铅笔的内芯是什么材质? a.铅 b.碳 c.石墨 答案:()
  2. 哪儿是世界上领土面积最大的国家? a.加拿大 b.俄罗斯 c.中国 d.德国 答案:()
  3. 谁是后世尊称的“药王”?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方法。

类图

设计模式系列:模板方法模式和建造者模式_第1张图片
template-method.png

场景

女娲带着小美女们造人了。造了三种人:白种人、黄种人、黑种人。人都有手臂、鼻子、眼睛、头、身体、腿,请用代码实现白种人、黄种人和黑种人

第一版代码(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实现子类,以支持残疾人的构造

建造者模式

概念

将一个复杂的构建与表示分离,使得同样的构建过程,能有不一样的表示。

类图

设计模式系列:模板方法模式和建造者模式_第2张图片
屏幕快照 2017-06-09 下午9.58.40.png

比较区别

  1. 建造者是使用组合方式实现不同的表示,而模板方法使用的是继承的方式。组合优于继承。
  2. 建造者抽象的是构建过程,而模板方法提取的是实现公共。

你可能感兴趣的:(设计模式系列:模板方法模式和建造者模式)