这篇来说一说java设计模式之builder模式

builder,就是创建者嘛,就是创建的模式。 做一个音乐app,怎么个启动流程呢? 正常,有广告,有启动图,有动画,还可以可以来个启动音乐(Hello Kugou)。 这个音乐程序的基础模型就有了。顺序就是看开发者的习惯了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package top.txiner.builder;

import java.util.ArrayList;

public abstract class Music {

    private ArrayList<String> sequence = new ArrayList<String>();

    protected abstract void playMusic();

    protected abstract void loadSplash();

    protected abstract void loadAd();

    protected abstract void showAnimation();

    public void run() {
        for (String command : sequence) {
            switch (command) {
                case "music":
                    this.playMusic();
                    break;
                case "splash":
                    this.loadSplash();
                    break;
                case "ad":
                    this.loadAd();
                    break;
                case "animation":
                    this.showAnimation();
                    break;
                default:
                    break;
            }
        }
    }
    public void setSequence(ArrayList<String> sequence){
        this.sequence=sequence;
    }


}

具体的,播放动画,或者是加载广告,都是各家自己的标准了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package top.txiner.builder;

import java.util.ArrayList;

public class TTPod extends Music {

    @Override
    protected void playMusic() {
        System.out.println("TTPod can play music ");
    }

    @Override
    protected void loadSplash() {
        System.out.println("TTPod splash is beautiful");
    }

    @Override
    protected void loadAd() {
        System.out.println("TTPod no ad");
    }

    @Override
    protected void showAnimation() {
        System.out.println("TTPod animation is splendid");
    }
}

package top.txiner.builder;

public class CloudMusic extends Music {
    @Override
    protected void playMusic() {
        System.out.println("CloudMusic plays music which fits you");
    }

    @Override
    protected void loadSplash() {
        System.out.println("CloudMusic sometimes load splash");
    }

    @Override
    protected void loadAd() {
        System.out.println("CloudMusic sometimes load ad");
    }

    @Override
    protected void showAnimation() {
        System.out.println("CloudMusic animation is wonderful");
    }
}

这样,创建app,就只需要自己写好一个序列,生成就好了。 等等,好事者称,我有国内版,国际版程序,顺序不一样,功能不一样,版本迭代的时候要求也不一样。 来,你来写呀! (有时候客户或者pm就是好事者) 大丈夫能屈能伸,我们既然感觉这样设计太麻烦,就干脆在音乐程序上面再套个接口,不管内部的实现,直接创建就好了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package top.txiner.builder;

import java.util.ArrayList;

public abstract class MusicBuilder {
    abstract void setSequence(ArrayList<String> sequence);
    abstract Music getModel();
}

package top.txiner.builder;

import java.util.ArrayList;

public class CloudMusicBuilder extends MusicBuilder {
    private CloudMusic cm=new CloudMusic();
    @Override
    void setSequence(ArrayList<String> sequence) {
        this.cm.setSequence(sequence);
    }

    @Override
    Music getModel() {
        return this.cm;
    }
}

package top.txiner.builder;

import java.util.ArrayList;

public class TTPodBuilder extends MusicBuilder {
    private TTPod ttPod=new TTPod();
    @Override
    void setSequence(ArrayList<String> sequence) {
        this.ttPod.setSequence(sequence);
    }

    @Override
    Music getModel() {
        return this.ttPod;
    }
}

这样,以后想用那个就用哪个model。 我们接下来再创建不同顺序的客户端。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package top.txiner.builder;

import java.util.ArrayList;

public class Director {
    private ArrayList<String> sequence=new ArrayList<>();
    private CloudMusicBuilder cmb=new CloudMusicBuilder();
    private TTPodBuilder tb=new TTPodBuilder();

    public TTPod getOverseaTTPod(){
        this.sequence.clear();
        this.sequence.add("splash");
        this.sequence.add("animation");
        this.sequence.add("music");
        this.tb.setSequence(this.sequence);
        return (TTPod) this.tb.getModel();
    }

    public TTPod getNativeTTPod(){
        this.sequence.clear();
        this.sequence.add("splash");
        this.sequence.add("ad");
        this.sequence.add("animation");
        this.sequence.add("ad");
        this.sequence.add("music");
        this.tb.setSequence(this.sequence);
        return (TTPod) this.tb.getModel();
    }

    public CloudMusic getOverseaCloudMusic(){
        this.sequence.clear();
        this.sequence.add("splash");
        this.sequence.add("animation");
        this.sequence.add("music");
        this.cmb.setSequence(this.sequence);
        return (CloudMusic) this.cmb.getModel();
    }

    public CloudMusic getNativeCloudMusic(){
        this.sequence.clear();
        this.sequence.add("splash");
        this.sequence.add("ad");
        this.sequence.add("animation");
        this.sequence.add("ad");
        this.sequence.add("music");
        this.cmb.setSequence(this.sequence);
        return (CloudMusic) this.cmb.getModel();
    }

}

这些,主程序直接使用就好了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package top.txiner.builder;

public class Client {
    public static void main(String[] args) {
        Director director = new Director();
        CloudMusic cm=director.getOverseaCloudMusic();
        cm.run();

        TTPod ttPod=director.getNativeTTPod();
        ttPod.run();
    }
}

看到这也发现了,虽然我自己设计出来,确实按照我自己的想法来,可是又是序列,又是调度者的,好麻烦啊! 我有时候并不想要这么多,就是单纯的想要个属性。 所以,有一个简化的builder(如果按照定义,已经不属于这种设计模式了)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package top.txiner.builder;

import java.util.ArrayList;

public class TTPod extends Music {

private int version;
    private String appName;
    private String appSource;
    private ArrayList<String> permissions;
    private String sound;
    private String size;
    private String icon;
    private String shortcut;
    private String ctr;

    public TTPod(){}

    public TTPod(Builder builder) {
        this.version = builder.version;
        this.appName = builder.appName;
        this.appSource = builder.appSource;
        this.permissions = builder.permissions;
        this.sound = builder.sound;
        this.size = builder.size;
        this.icon = builder.icon;
        this.shortcut = builder.shortcut;
        this.ctr = builder.ctr;
    }


    public static class Builder{
        private int version;
        private String appName;
        private String appSource;
        private ArrayList<String> permissions;
        private String sound;
        private String size;
        private String icon;
        private String shortcut;
        private String ctr;
        public Builder() {

        }

        public Builder setVersion(int version) {
            this.version = version;
            return this;
        }

        public Builder setAppName(String appName) {
            this.appName = appName;
            return this;
        }

        public Builder setAppSource(String appSource) {
            this.appSource = appSource;
            return this;
        }

        public Builder setPermissions(ArrayList<String> permissions) {
            this.permissions = permissions;
            return this;
        }

        public Builder setSound(String sound) {
            this.sound = sound;
            return this;
        }

        public Builder setSize(String size) {
            this.size = size;
            return this;
        }

        public Builder setIcon(String icon) {
            this.icon = icon;
            return this;
        }

        public Builder setShortcut(String shortcut) {
            this.shortcut = shortcut;
            return this;
        }

        public Builder setCtr(String ctr){
            this.ctr=ctr;
            return this;
        }

        public TTPod build(){
            return new TTPod(this);
        }
    }

}

我们要使用也很简单

1
new TTPod.Builder().setVersion().build();

好了,这下很是清净了。