設(shè)計模式系列——建造者模式-Builder Pattern

沒有人買車會只買一個輪胎或者方向盤,大家買的都是一輛包含輪胎、方向盤和發(fā)動機(jī)等多個部件的完整汽車。如何將這些部件組裝成一輛完整的汽車并返回給用戶,這是建造者模式需要解決的問題。建造者模式又稱為生成器模式,它是一種較為復(fù)雜、使用頻率也相對較低的創(chuàng)建型模式。建造者模式為客戶端返回的不是一個簡單的產(chǎn)品,而是一個由多個部件組成的復(fù)雜產(chǎn)品。


1.游戲角色設(shè)計

Sunny軟件公司游戲開發(fā)小組決定開發(fā)一款名為《Sunny群俠傳》的網(wǎng)絡(luò)游戲,該游戲采用主流的RPG(Role Playing Game,角色扮演游戲)模式,玩家可以在游戲中扮演虛擬世界中的一個特定角色,角色根據(jù)不同的游戲情節(jié)和統(tǒng)計數(shù)據(jù)(如力量、魔法、技能等)具有不同的能力,角色也會隨著不斷升級而擁有更加強(qiáng)大的能力。

作為RPG游戲的一個重要組成部分,需要對游戲角色進(jìn)行設(shè)計,而且隨著該游戲的升級將不斷增加新的角色。不同類型的游戲角色,其性別、臉型、服裝、發(fā)型等外部特性都有所差異,例如“天使”擁有美麗的面容和披肩的長發(fā),并身穿一襲白裙;而“惡魔”極其丑陋,留著光頭并穿一件刺眼的黑衣。

Sunny公司決定開發(fā)一個小工具來創(chuàng)建游戲角色,可以創(chuàng)建不同類型的角色并可以靈活增加新的角色。

Sunny公司的開發(fā)人員通過分析發(fā)現(xiàn),游戲角色是一個復(fù)雜對象,它包含性別、臉型等多個組成部分,不同的游戲角色其組成部分有所差異:


(注:本圖中的游戲角色造型來源于網(wǎng)絡(luò),特此說明)

無論是何種造型的游戲角色,它的創(chuàng)建步驟都大同小異,都需要逐步創(chuàng)建其組成部分,再將各組成部分裝配成一個完整的游戲角色。如何一步步創(chuàng)建一個包含多個組成部分的復(fù)雜對象,建造者模式為解決此類問題而誕生。

2.建造者模式概述

建造者模式是較為復(fù)雜的創(chuàng)建型模式,它將客戶端與包含多個組成部分(或部件)的復(fù)雜對象的創(chuàng)建過程分離,客戶端無須知道復(fù)雜對象的內(nèi)部組成部分與裝配方式,只需要知道所需建造者的類型即可。它關(guān)注如何一步一步創(chuàng)建一個的復(fù)雜對象,不同的具體建造者定義了不同的創(chuàng)建過程,且具體建造者相互獨立,增加新的建造者非常方便,無須修改已有代碼,系統(tǒng)具有較好的擴(kuò)展性。

建造者模式定義如下:

建造者模式(Builder Pattern):將一個復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。建造者模式是一種對象創(chuàng)建型模式。

建造者模式一步一步創(chuàng)建一個復(fù)雜的對象,它允許用戶只通過指定復(fù)雜對象的類型和內(nèi)容就可以構(gòu)建它們,用戶不需要知道內(nèi)部的具體構(gòu)建細(xì)節(jié):


在建造者模式結(jié)構(gòu)圖中包含如下幾個角色:

●Builder(抽象建造者):它為創(chuàng)建一個產(chǎn)品Product對象的各個部件指定抽象接口,在該接口中一般聲明兩類方法,一類方法是buildPartX(),它們用于創(chuàng)建復(fù)雜對象的各個部件;另一類方法是getResult(),它們用于返回復(fù)雜對象。Builder既可以是抽象類,也可以是接口。

●ConcreteBuilder(具體建造者):它實現(xiàn)了Builder接口,實現(xiàn)各個部件的具體構(gòu)造和裝配方法,定義并明確它所創(chuàng)建的復(fù)雜對象,也可以提供一個方法返回創(chuàng)建好的復(fù)雜產(chǎn)品對象。

●Product(產(chǎn)品角色):它是被構(gòu)建的復(fù)雜對象,包含多個組成部件,具體建造者創(chuàng)建該產(chǎn)品的內(nèi)部表示并定義它的裝配過程。

●Director(指揮者):指揮者又稱為導(dǎo)演類,它負(fù)責(zé)安排復(fù)雜對象的建造次序,指揮者與抽象建造者之間存在關(guān)聯(lián)關(guān)系,可以在其construct()建造方法中調(diào)用建造者對象的部件構(gòu)造與裝配方法,完成復(fù)雜對象的建造??蛻舳艘话阒恍枰c指揮者進(jìn)行交互,在客戶端確定具體建造者的類型,并實例化具體建造者對象(也可以通過配置文件和反射機(jī)制),然后通過指揮者類的構(gòu)造函數(shù)或者Setter方法將該對象傳入指揮者類中。

在建造者模式的定義中提到了復(fù)雜對象,那么什么是復(fù)雜對象?簡單來說,復(fù)雜對象是指那些包含多個成員屬性的對象,這些成員屬性也稱為部件或零件,如汽車包括方向盤、發(fā)動機(jī)、輪胎等部件,電子郵件包括發(fā)件人、收件人、主題、內(nèi)容、附件等部件,一個典型的復(fù)雜對象類代碼示例如下:

class Product{

private? String partA; //定義部件,部件可以是任意類型,包括值類型和引用類型

private? String partB;

private? String partC;

//partA的Getter方法和Setter方法省略

//partB的Getter方法和Setter方法省略

//partC的Getter方法和Setter方法省略

}

在抽象建造者類中定義了產(chǎn)品的創(chuàng)建方法和返回方法,其典型代碼如下:

abstract class Builder{

//創(chuàng)建產(chǎn)品對象

protected? Product product=new Product();

public? abstract void buildPartA();

public? abstract void buildPartB();

public? abstract void buildPartC();

//返回產(chǎn)品對象

public? Product getResult(){

return? product;

}

}

在抽象類Builder中聲明了一系列抽象的buildPartX()方法用于創(chuàng)建復(fù)雜產(chǎn)品的各個部件,具體建造過程在ConcreteBuilder中實現(xiàn),此外還提供了工廠方法getResult(),用于返回一個建造好的完整產(chǎn)品。

在ConcreteBuilder中實現(xiàn)了buildPartX()方法,通過調(diào)用Product的setPartX()方法可以給產(chǎn)品對象的成員屬性設(shè)值。不同的具體建造者在實現(xiàn)buildPartX()方法時將有所區(qū)別,如setPartX()方法的參數(shù)可能不一樣,在有些具體建造者類中某些setPartX()方法無須實現(xiàn)(提供一個空實現(xiàn))。而這些對于客戶端來說都無須關(guān)心,客戶端只需知道具體建造者類型即可。

在建造者模式的結(jié)構(gòu)中還引入了一個指揮者類Director,該類主要有兩個作用:一方面它隔離了客戶與創(chuàng)建過程;另一方面它控制產(chǎn)品的創(chuàng)建過程,包括某個buildPartX()方法是否被調(diào)用以及多個buildPartX()方法調(diào)用的先后次序等。指揮者針對抽象建造者編程,客戶端只需要知道具體建造者的類型,即可通過指揮者類調(diào)用建造者的相關(guān)方法,返回一個完整的產(chǎn)品對象。在實際生活中也存在類似指揮者一樣的角色,如一個客戶去購買電腦,電腦銷售人員相當(dāng)于指揮者,只要客戶確定電腦的類型,電腦銷售人員可以通知電腦組裝人員給客戶組裝一臺電腦。指揮者類的代碼示例如下:

class Director{

private? Builder builder;

public? Director(Builder builder){

this.builder=builder;

}

public? void setBuilder(Builder builder){

this.builder=builer;

}

//產(chǎn)品構(gòu)建與組裝方法

public Product construct(){

builder.buildPartA();

builder.buildPartB();

builder.buildPartC();

return builder.getResult();

}

}

在指揮者類中可以注入一個抽象建造者類型的對象,其核心在于提供了一個建造方法construct(),在該方法中調(diào)用了builder對象的構(gòu)造部件的方法,最后返回一個產(chǎn)品對象。

對于客戶端而言,只需關(guān)心具體的建造者即可,一般情況下,客戶端類代碼片段如下所示:

……

Builder? builder = new ConcreteBuilder(); //可通過配置文件實現(xiàn)

Director director = new? Director(builder);

Product product = director.construct();

……

可以通過配置文件來存儲具體建造者類ConcreteBuilder的類名,使得更換新的建造者時無須修改源代碼,系統(tǒng)擴(kuò)展更為方便。在客戶端代碼中,無須關(guān)心產(chǎn)品對象的具體組裝過程,只需指定具體建造者的類型即可。

建造者模式與抽象工廠模式有點相似,但是建造者模式返回一個完整的復(fù)雜產(chǎn)品,而抽象工廠模式返回一系列相關(guān)的產(chǎn)品;在抽象工廠模式中,客戶端通過選擇具體工廠來生成所需對象,而在建造者模式中,客戶端通過指定具體建造者類型并指導(dǎo)Director類如何去生成對象,側(cè)重于一步步構(gòu)造一個復(fù)雜對象,然后將結(jié)果返回。如果將抽象工廠模式看成一個汽車配件生產(chǎn)廠,生成不同類型的汽車配件,那么建造者模式就是一個汽車組裝廠,通過對配件進(jìn)行組裝返回一輛完整的汽車。

3完整解決方案

Sunny公司開發(fā)人員決定使用建造者模式來實現(xiàn)游戲角色的創(chuàng)建


ActorController充當(dāng)指揮者,ActorBuilder充當(dāng)抽象建造者,HeroBuilder、AngelBuilder和DevilBuilder充當(dāng)具體建造者,Actor充當(dāng)復(fù)雜產(chǎn)品。完整代碼如下所示:

//Actor角色類:復(fù)雜產(chǎn)品,考慮到代碼的可讀性,只列出部分成員屬性,且成員屬性的類型均為String,真實情況下,有些成員屬性的類型需自定義

class Actor

{

private? String type; //角色類型

private? String sex; //性別

private? String face; //臉型

private? String costume; //服裝

private? String hairstyle; //發(fā)型

public? void setType(String type) {

this.type? = type;

}

public? void setSex(String sex) {

this.sex? = sex;

}

public? void setFace(String face) {

this.face? = face;

}

public? void setCostume(String costume) {

this.costume? = costume;

}

public? void setHairstyle(String hairstyle) {

this.hairstyle? = hairstyle;

}

public? String getType() {

return? (this.type);

}

public? String getSex() {

return? (this.sex);

}

public? String getFace() {

return? (this.face);

}

public? String getCostume() {

return? (this.costume);

}

public? String getHairstyle() {

return? (this.hairstyle);

}

}

//角色建造器:抽象建造者

abstract class ActorBuilder

{

protected? Actor actor = new Actor();

public? abstract void buildType();

public? abstract void buildSex();

public? abstract void buildFace();

public? abstract void buildCostume();

public? abstract void buildHairstyle();

//工廠方法,返回一個完整的游戲角色對象

public Actor createActor()

{

return actor;

}

}

//英雄角色建造器:具體建造者

class HeroBuilder extends ActorBuilder

{

public? void buildType()

{

actor.setType("英雄");

}

public? void buildSex()

{

actor.setSex("男");

}

public? void buildFace()

{

actor.setFace("英俊");

}

public? void buildCostume()

{

actor.setCostume("盔甲");

}

public? void buildHairstyle()

{

actor.setHairstyle("飄逸");

}

}

//天使角色建造器:具體建造者

class AngelBuilder extends ActorBuilder

{

public? void buildType()

{

actor.setType("天使");

}

public? void buildSex()

{

actor.setSex("女");

}

public? void buildFace()

{

actor.setFace("漂亮");

}

public? void buildCostume()

{

actor.setCostume("白裙");

}

public? void buildHairstyle()

{

actor.setHairstyle("披肩長發(fā)");

}

}

//惡魔角色建造器:具體建造者

class DevilBuilder extends ActorBuilder

{

public? void buildType()

{

actor.setType("惡魔");

}

public? void buildSex()

{

actor.setSex("妖");

}

public? void buildFace()

{

actor.setFace("丑陋");

}

public? void buildCostume()

{

actor.setCostume("黑衣");

}

public? void buildHairstyle()

{

actor.setHairstyle("光頭");

}

}

指揮者類ActorController定義了construct()方法,該方法擁有一個抽象建造者ActorBuilder類型的參數(shù),在該方法內(nèi)部實現(xiàn)了游戲角色對象的逐步構(gòu)建,代碼如下所示:

//游戲角色創(chuàng)建控制器:指揮者

class ActorController

{

//逐步構(gòu)建復(fù)雜產(chǎn)品對象

public Actor construct(ActorBuilder ab)

{

Actor actor;

ab.buildType();

ab.buildSex();

ab.buildFace();

ab.buildCostume();

ab.buildHairstyle();

actor=ab.createActor();

return actor;

}

}

為了提高系統(tǒng)的靈活性和可擴(kuò)展性,我們將具體建造者類的類名存儲在配置文件中,并通過工具類XMLUtil來讀取配置文件并反射生成對象,XMLUtil類的代碼如下所示:

import javax.xml.parsers.*;

import org.w3c.dom.*;

import org.xml.sax.SAXException;

importJava.io.*;

class XMLUtil

{

//該方法用于從XML配置文件中提取具體類類名,并返回一個實例對象

public? static Object getBean()

{

try

{

//創(chuàng)建文檔對象

DocumentBuilderFactory? dFactory = DocumentBuilderFactory.newInstance();

DocumentBuilder? builder = dFactory.newDocumentBuilder();

Document? doc;

doc? = builder.parse(new File("config.xml"));

//獲取包含類名的文本節(jié)點

NodeList? nl = doc.getElementsByTagName("className");

Node? classNode=nl.item(0).getFirstChild();

String? cName=classNode.getNodeValue();

//通過類名生成實例對象并將其返回

Class c=Class.forName(cName);

Object obj=c.newInstance();

return obj;

}

catch(Exception e)

{

e.printStackTrace();

return null;

}

}

}

配置文件config.xml中存儲了具體建造者類的類名,代碼如下所示:


AngelBuilder

編寫如下客戶端測試代碼:

class Client

{

public? static void main(String args[])

{

ActorBuilder ab; //針對抽象建造者編程

ab =? (ActorBuilder)XMLUtil.getBean(); //反射生成具體建造者對象

ActorController ac = new? ActorController();

Actor actor;

actor = ac.construct(ab); //通過指揮者創(chuàng)建完整的建造者對象

String? type = actor.getType();

System.out.println(type? + "的外觀:");

System.out.println("性別:" + actor.getSex());

System.out.println("面容:" + actor.getFace());

System.out.println("服裝:" + actor.getCostume());

System.out.println("發(fā)型:" + actor.getHairstyle());

}

}

編譯并運行程序,輸出結(jié)果如下:

天使的外觀:

性別:女

面容:漂亮

服裝:白裙

發(fā)型:披肩長發(fā)

在建造者模式中,客戶端只需實例化指揮者類,指揮者類針對抽象建造者編程,客戶端根據(jù)需要傳入具體的建造者類型,指揮者將指導(dǎo)具體建造者一步一步構(gòu)造一個完整的產(chǎn)品(逐步調(diào)用具體建造者的buildX()方法),相同的構(gòu)造過程可以創(chuàng)建完全不同的產(chǎn)品。在游戲角色實例中,如果需要更換角色,只需要修改配置文件,更換具體角色建造者類即可;如果需要增加新角色,可以增加一個新的具體角色建造者類作為抽象角色建造者的子類,再修改配置文件即可,原有代碼無須修改,完全符合“開閉原則”。

4關(guān)于Director的進(jìn)一步討論

指揮者類Director在建造者模式中扮演非常重要的作用,簡單的Director類用于指導(dǎo)具體建造者如何構(gòu)建產(chǎn)品,它按一定次序調(diào)用Builder的buildPartX()方法,控制調(diào)用的先后次序,并向客戶端返回一個完整的產(chǎn)品對象。下面我們討論幾種Director的高級應(yīng)用方式:

1.省略Director

在有些情況下,為了簡化系統(tǒng)結(jié)構(gòu),可以將Director和抽象建造者Builder進(jìn)行合并,在Builder中提供逐步構(gòu)建復(fù)雜產(chǎn)品對象的construct()方法。由于Builder類通常為抽象類,因此可以將construct()方法定義為靜態(tài)(static)方法。如果將游戲角色設(shè)計中的指揮者類ActorController省略,ActorBuilder類的代碼修改如下:

abstract class ActorBuilder

{

protected static Actor actor = new? Actor();

public? abstract void buildType();

public? abstract void buildSex();

public? abstract void buildFace();

public? abstract void buildCostume();

public? abstract void buildHairstyle();

public static Actor? construct(ActorBuilder ab)

{

ab.buildType();

ab.buildSex();

ab.buildFace();

ab.buildCostume();

ab.buildHairstyle();

return actor;

}

}

對應(yīng)的客戶端代碼也將發(fā)生修改,其代碼片段如下所示:

……

ActorBuilder? ab;

ab? = (ActorBuilder)XMLUtil.getBean();

Actor? actor;

actor =? ActorBuilder.construct(ab);

……

除此之外,還有一種更簡單的處理方法,可以將construct()方法的參數(shù)去掉,直接在construct()方法中調(diào)用buildPartX()方法,代碼如下所示:

abstract class ActorBuilder

{

protected? Actor actor = new Actor();

public? abstract void buildType();

public? abstract void buildSex();

public? abstract void buildFace();

public? abstract void buildCostume();

public? abstract void buildHairstyle();

public Actor construct()

{

this.buildType();

this.buildSex();

this.buildFace();

this.buildCostume();

this.buildHairstyle();

return actor;

}

}

客戶端代碼代碼片段如下所示:

……

ActorBuilder? ab;

ab? = (ActorBuilder)XMLUtil.getBean();

Actor? actor;

actor = ab.construct();

……

此時,construct()方法定義了其他buildPartX()方法調(diào)用的次序,為其他方法的執(zhí)行提供了一個流程模板,這與我們在后面要學(xué)習(xí)的模板方法模式非常類似。

以上兩種對Director類的省略方式都不影響系統(tǒng)的靈活性和可擴(kuò)展性,同時還簡化了系統(tǒng)結(jié)構(gòu),但加重了抽象建造者類的職責(zé),如果construct()方法較為復(fù)雜,待構(gòu)建產(chǎn)品的組成部分較多,建議還是將construct()方法單獨封裝在Director中,這樣做更符合“單一職責(zé)原則”。

2.鉤子方法的引入

建造者模式除了逐步構(gòu)建一個復(fù)雜產(chǎn)品對象外,還可以通過Director類來更加精細(xì)地控制產(chǎn)品的創(chuàng)建過程,例如增加一類稱之為鉤子方法(HookMethod)的特殊方法來控制是否對某個buildPartX()的調(diào)用。

鉤子方法的返回類型通常為boolean類型,方法名一般為isXXX(),鉤子方法定義在抽象建造者類中。例如我們可以在游戲角色的抽象建造者類ActorBuilder中定義一個方法isBareheaded(),用于判斷某個角色是否為“光頭(Bareheaded)”,在ActorBuilder為之提供一個默認(rèn)實現(xiàn),其返回值為false,代碼如下所示:

abstract class ActorBuilder

{

protected? Actor actor = new Actor();

public? abstract void buildType();

public? abstract void buildSex();

public? abstract void buildFace();

public? abstract void buildCostume();

public? abstract void buildHairstyle();

//鉤子方法

public boolean isBareheaded()

{

return false;

}

public? Actor createActor()

{

return? actor;

}

}

如果某個角色無須構(gòu)建頭發(fā)部件,例如“惡魔(Devil)”,則對應(yīng)的具體建造器DevilBuilder將覆蓋isBareheaded()方法,并將返回值改為true,代碼如下所示:

class DevilBuilder extends ActorBuilder

{

public? void buildType()

{

actor.setType("惡魔");

}

public? void buildSex()

{

actor.setSex("妖");

}

public? void buildFace()

{

actor.setFace("丑陋");

}

public? void buildCostume()

{

actor.setCostume("黑衣");

}

public? void buildHairstyle()

{

actor.setHairstyle("光頭");

}

//覆蓋鉤子方法

public boolean isBareheaded()

{

return true;

}

}

此時,指揮者類ActorController的代碼修改如下:

class ActorController

{

public? Actor construct(ActorBuilder ab)

{

Actor? actor;

ab.buildType();

ab.buildSex();

ab.buildFace();

ab.buildCostume();

//通過鉤子方法來控制產(chǎn)品的構(gòu)建

if(!ab.isBareheaded())

{

ab. buildHairstyle();

}

actor=ab.createActor();

return? actor;

}

}

當(dāng)在客戶端代碼中指定具體建造者類型并通過指揮者來實現(xiàn)產(chǎn)品的逐步構(gòu)建時,將調(diào)用鉤子方法isBareheaded()來判斷游戲角色是否有頭發(fā),如果isBareheaded()方法返回true,即沒有頭發(fā),則跳過構(gòu)建發(fā)型的方法buildHairstyle();否則將執(zhí)行buildHairstyle()方法。通過引入鉤子方法,我們可以在Director中對復(fù)雜產(chǎn)品的構(gòu)建進(jìn)行精細(xì)的控制,不僅指定buildPartX()方法的執(zhí)行順序,還可以控制是否需要執(zhí)行某個buildPartX()方法。

5.建造者模式總結(jié)

建造者模式的核心在于如何一步步構(gòu)建一個包含多個組成部件的完整對象,使用相同的構(gòu)建過程構(gòu)建不同的產(chǎn)品,在軟件開發(fā)中,如果我們需要創(chuàng)建復(fù)雜對象并希望系統(tǒng)具備很好的靈活性和可擴(kuò)展性可以考慮使用建造者模式。

1.主要優(yōu)點

建造者模式的主要優(yōu)點如下:

(1)在建造者模式中,客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對象。

(2)每一個具體建造者都相對獨立,而與其他的具體建造者無關(guān),因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產(chǎn)品對象。由于指揮者類針對抽象建造者編程,增加新的具體建造者無須修改原有類庫的代碼,系統(tǒng)擴(kuò)展方便,符合“開閉原則”

(3)可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過程。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過程更加清晰,也更方便使用程序來控制創(chuàng)建過程。

2.主要缺點

建造者模式的主要缺點如下:

(1)建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點,其組成部分相似,如果產(chǎn)品之間的差異性很大,例如很多組成部分都不相同,不適合使用建造者模式,因此其使用范圍受到一定的限制。

(2)如果產(chǎn)品的內(nèi)部變化復(fù)雜,可能會導(dǎo)致需要定義很多具體建造者類來實現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大,增加系統(tǒng)的理解難度和運行成本。

3.適用場景

在以下情況下可以考慮使用建造者模式:

(1)需要生成的產(chǎn)品對象有復(fù)雜的內(nèi)部結(jié)構(gòu),這些產(chǎn)品對象通常包含多個成員屬性。

(2)需要生成的產(chǎn)品對象的屬性相互依賴,需要指定其生成順序。

(3)對象的創(chuàng)建過程獨立于創(chuàng)建該對象的類。在建造者模式中通過引入了指揮者類,將創(chuàng)建過程封裝在指揮者類中,而不在建造者類和客戶類中。

(4)隔離復(fù)雜對象的創(chuàng)建和使用,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,623評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • 面向?qū)ο蟮牧笤瓌t 單一職責(zé)原則 所謂職責(zé)是指類變化的原因。如果一個類有多于一個的動機(jī)被改變,那么這個類就具有多于...
    JxMY閱讀 1,017評論 1 3
  • 1 場景問題# 1.1 繼續(xù)導(dǎo)出數(shù)據(jù)的應(yīng)用框架## 在討論工廠方法模式的時候,提到了一個導(dǎo)出數(shù)據(jù)的應(yīng)用框架。 對于...
    七寸知架構(gòu)閱讀 6,125評論 1 64
  • 三、羞愧情緒的原因是什么? 生活在一個從小就被規(guī)范的社會,我們很怕別人對我們的不認(rèn)同,不滿意、或者沒有符合別人的邏...
    洗澡真快活閱讀 2,048評論 0 1

友情鏈接更多精彩內(nèi)容