版權聲明:轉載必須註明本文轉自曉_晨的博客:http://blog.csdn.net/niunai112
目錄
導航
設計模式之六大設計原則
設計模式(一)單例模式
設計模式(二)工廠模式
設計模式(三)策略模式
設計模式(四)適配器模式
設計模式(五)享元模式
設計模式(六)建造者模式
設計模式(七)原型模式
設計模式(八)橋接模式
設計模式(九)外觀模式
設計模式(十)組合模式
設計模式(十一)裝飾器模式
設計模式(十二)代理模式
設計模式(十三)迭代器模式
設計模式(十四)觀察者模式
設計模式(十五)中介者模式
設計模式(十六)命令模式
設計模式(十七)狀態模式
設計模式(十八)訪問者模式
設計模式(十九)責任鏈模式
設計模式(二十)解釋器模式
設計模式(二十一)備忘錄模式
設計模式(二十二)模板模式
設計模式總結篇(爲什麼要學習設計模式,學習設計模式的好處)
前言
在開發過程,有的時候會出現一個複雜對象的創建工作,這個對象一般組裝模式固定,但是其中的參數會變,比如像電腦,汽車等,可拆分的東西,基本都能使用這個模式,只是看有沒有必要,一些本來就是固定死的東西,用工廠模式或者享元模式會更好。
例子
假如你是一家雲提供商,你的客戶需要不同種類的產品,你要給不同客戶提供產品。
/***
*
*@Author ChenjunWang
*@Description:產品類,服務器有操作系統,所用語言,所選服務器和所選數據庫
*@Date: Created in 21:05 2018/3/20
*@Modified By:
*
*/
public class ServerProduct {
String os;
String language;
String server;
String database;
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getEnvironment() {
return "ServerProduct{" +
"os='" + os + '\'' +
", language='" + language + '\'' +
", server='" + server + '\'' +
", database='" + database + '\'' +
'}';
}
}
假設有個客戶選了經典套餐
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:19 2018/3/20
*@Modified By:
*
*/
public class Customer {
public static void main(String[] args) {
ServerProduct customer = new ServerProduct();
customer.setOs("Ubuntu");
customer.setLanguage("Java");;
customer.setDatabase("Mysql");
customer.setServer("Tomcat");
System.out.println("客戶1要的環境:" + customer.getEnvironment());
}
}
運行結果如下
-------------------------------
客戶1要的環境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
沒問題,環境出來了,客戶很滿意,後來又有一個客戶說系統要centos,然後我們又要把全部流程走一遍
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:19 2018/3/20
*@Modified By:
*
*/
public class Customer {
public static void main(String[] args) {
ServerProduct customer = new ServerProduct();
customer.setOs("Ubuntu");
customer.setLanguage("Java");;
customer.setDatabase("Mysql");
customer.setServer("Tomcat");
System.out.println("客戶1要的環境:" + customer.getEnvironment());
ServerProduct customer2 = new ServerProduct();
customer2.setOs("Ubuntu");
customer2.setLanguage("Java");;
customer2.setDatabase("Mysql");
customer2.setServer("Tomcat");
System.out.println("客戶2要的環境:" + customer2.getEnvironment());
}
}
運行結果如下
-------------------------------
客戶1要的環境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
客戶2要的環境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
這樣每次創建一個環境都需要寫大量的重複代碼,所以LZ
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:12 2018/3/20
*@Modified By:
*
*/
public interface Builder {
Builder installOS(String OS);
Builder installLanguage(String language);
Builder installServer(String server);
Builder installDatabase(String database);
ServerProduct getProduct();
}
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 22:04 2018/3/20
*@Modified By:
*
*/
public class Classic implements Builder{
private ServerProduct serverProduct = new ServerProduct();
@Override
public Builder installOS(String OS) {
serverProduct.os = OS;
return this;
}
@Override
public Builder installLanguage(String language) {
serverProduct.language = language;
return this;
}
@Override
public Builder installServer(String server) {
serverProduct.server = server;
return this;
}
@Override
public Builder installDatabase(String database) {
serverProduct.database = database;
return this;
}
@Override
public ServerProduct getProduct() {
return serverProduct;
}
}
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 22:11 2018/3/20
*@Modified By:
*
*/
public class Director {
private Builder builder = new Classic();
public ServerProduct createClassicUbuntuEnvironment(){
builder.installOS("Ubuntu").installLanguage("Java").installServer("Tomcat").installDatabase("Mysql");
return builder.getProduct();
}
public ServerProduct createClassicCentOSEnvironment(){
builder.installOS("CentOS").installLanguage("Java").installServer("Tomcat").installDatabase("Mysql");
return builder.getProduct();
}
}
public class Customer {
public static void main(String[] args) {
Director director = new Director();
ServerProduct classicCentOSEnvironment1 = director.createClassicCentOSEnvironment();
System.out.println("創建第一個環境:" + classicCentOSEnvironment1.getEnvironment());
ServerProduct classicCentOSEnvironment2 = director.createClassicUbuntuEnvironment();
System.out.println("創建第二個環境:" + classicCentOSEnvironment2.getEnvironment());
}
}
運行結果如下
--------------------------
創建第一個環境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
創建第二個環境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
UML圖
其實,建造者模式到這就結束了,但是LZ還是要拓展一下,這裏存在一個大問題,就是假如使用上面的方法的話,director 再次調用create方法的話,之前的信息就會被替換掉,因爲他們引用的是同一個對象。所以Main應該要按下面這樣寫纔對。
public class Customer {
public static void main(String[] args) {
Director director = new Director();
ServerProduct classicCentOSEnvironment1 = director.createClassicCentOSEnvironment();
System.out.println("創建第一個環境:" + classicCentOSEnvironment1.getEnvironment());
director = new Director();
classicCentOSEnvironment2 = director.createClassicUbuntuEnvironment();
System.out.println("創建第二個環境:" + classicCentOSEnvironment2.getEnvironment());
System.out.println("創建第一個環境:" + classicCentOSEnvironment1.getEnvironment());
}
}
---------------------------------------------------
創建第一個環境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
創建第二個環境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
創建第一個環境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
這樣就沒有什麼問題了。每次新建出來的環境都是不同的對象。
總結
優點
建造者模式中,客戶端不必知道產品內部組成的細節,將產品本身與產品的創建過程解耦,使得相同的創建過程可以創建不同的產品對象。
每一個具體建造者都相對獨立,而與其他的具體建造者無關,因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產品對象。由於指揮者類針對抽象建造者編程,增加新的具體建造者無須修改原有類庫的代碼,系統擴展方便,符合“開閉原則”。
可以更加精細地控制產品的創建過程。將複雜產品的創建步驟分解在不同的方法中,使得創建過程更加清晰。
缺點
建造者模式所創建的產品具有較多的共同點,其組成部分相似,如果產品之間的差異性很大,不適合使用建造者模式,因此其使用範圍受到一定的限制。
如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大,增加系統的理解難度和運行成本。
Git地址
本篇實例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/builder
有什麼不懂或者不對的地方,歡迎留言。
喜歡LZ文章的小夥伴們,可以關注一波,也可以留言,LZ會回你們的。
覺得寫得不錯的小夥伴,歡迎轉載,但請附上原文地址,謝謝^_^!