目錄
一、創(chuàng)建型模式
一句話概括
1.1、工廠模式
1.1.1、簡(jiǎn)單工廠模式(非 23 種經(jīng)典設(shè)計(jì)模式)
概述
案例
1.1.2、靜態(tài)工廠(擴(kuò)展)
1.1.3、工廠方法模式
概念
案例
1.2、建造者模式
1.2.1、概念
1.2.2、案例
1.2.3、建造者模式擴(kuò)展:鏈?zhǔn)骄幊痰讓?/p>
1.3、工廠方法模式 VS 建造者模式
一、創(chuàng)建型模式
一句話概括
創(chuàng)建型模式:教你如果創(chuàng)建對(duì)象.
1.1、工廠模式
1.1.1、簡(jiǎn)單工廠模式(非 23 種經(jīng)典設(shè)計(jì)模式)
概述
簡(jiǎn)單工廠不是一種設(shè)計(jì)模式,反而比較像是一種編程習(xí)慣.
簡(jiǎn)單工廠包含一下角色:
- 抽象產(chǎn)品 :定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
- 具體產(chǎn)品 :實(shí)現(xiàn)或者繼承抽象產(chǎn)品的子類
- 具體工廠 :提供了創(chuàng)建產(chǎn)品的方法,調(diào)用者通過(guò)該方法來(lái)獲取產(chǎn)品
案例
需求:設(shè)計(jì)一個(gè)咖啡店點(diǎn)餐系統(tǒng).
思路:設(shè)計(jì)一個(gè)咖啡類(Coffee),并定義其兩個(gè)子類(美式咖啡【AmericanCoffee】和拿鐵咖啡 【LatteCoffee】);再設(shè)計(jì)一個(gè)咖啡店類(CoffeeStore),咖啡店具有點(diǎn)咖啡的功能。
以下代碼為空架.
/**
* 咖啡
*/
public abstract class Coffee {
public abstract String getName();
public void addSugar() {
System.out.println("加糖");
}
public void addWeight() {
System.out.println("加量");
}
}
/**
* 美式咖啡
*/
public class AmericanCoffee extends Coffee{
@Override
public String getName() {
return "美式咖啡";
}
}
/**
* 拿鐵咖啡
*/
public class LatteCoffee extends Coffee{
@Override
public String getName() {
return "拿鐵咖啡";
}
}
/**
* 咖啡店
*/
public class CoffeeStore {
public Coffee orderCoffee(String type) {
//1.根據(jù)訂單類型選取對(duì)應(yīng)的咖啡
Coffee coffee = null;
if (type == null || type.equals("")) {
throw new RuntimeException("type 非法");
} else if (type.equals("ac")) {
coffee = new AmericanCoffee();
} else if(type.equals("lc")) {
coffee = new LatteCoffee();
} else {
throw new RuntimeException("type 非法");
}
//2.加糖加量
coffee.addSugar();
coffee.addWeight();
return coffee;
}
}
/**
* 測(cè)試客戶端
*/
public class ClientCoffee {
public static void main(String[] args) {
CoffeeStore store = new CoffeeStore();
Coffee coffee = store.orderCoffee("ac");
System.out.println(coffee.getName());
}
}
可以產(chǎn)出上述代碼中 Coffee 類為抽象產(chǎn)品,AmericanCoffee 和 LatteCoffee 為具體產(chǎn)品,但是沒有抽象工廠.? 以下使用 簡(jiǎn)單工廠模式 對(duì)上述代碼進(jìn)行改造.
public abstract class Coffee {
public abstract String getName();
public void addSugar() {
System.out.println("加糖");
}
public void addWeight() {
System.out.println("加量");
}
}
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿鐵咖啡";
}
}
/**
* 簡(jiǎn)單工廠模式
*/
public class SimpleCoffeeFactory {
public Coffee createCoffee(String type) {
//1.根據(jù)訂單類型選取對(duì)應(yīng)的咖啡
Coffee coffee = null;
if (type == null || type.equals("")) {
throw new RuntimeException("type 非法");
} else if (type.equals("ac")) {
coffee = new AmericanCoffee();
} else if(type.equals("lc")) {
coffee = new LatteCoffee();
} else {
throw new RuntimeException("type 非法");
}
//2.加糖加量
coffee.addSugar();
coffee.addWeight();
return coffee;
}
}
public class CoffeeStore {
public Coffee orderCoffee(String type) {
//1.讓工廠來(lái)創(chuàng)建對(duì)象
SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
Coffee coffee = factory.createCoffee(type);
//2.加料
coffee.addWeight();
coffee.addSugar();
return coffee;
}
}
public class ClientCoffee {
public static void main(String[] args) {
CoffeeStore store = new CoffeeStore();
Coffee coffee = store.orderCoffee("ac");
System.out.println(coffee.getName());
}
}
上述代碼中有了 SimpleCoffeeFactory ,使得 Coffee 的具體實(shí)現(xiàn)類和 CoffeeStore 解耦合,但是又產(chǎn)生了 CoffeeStore 和 SimpleCoffeeFactory 對(duì)象的耦合. 后期我們?nèi)绻有碌目Х绕贩N,勢(shì)必需要修改 SimpleCoffeeFactory 的代碼,違反了開閉原則.
優(yōu)點(diǎn):
解耦合:將對(duì)象的創(chuàng)建和業(yè)務(wù)邏輯層分開,避免將來(lái)修改客戶端代碼.? 入股偶要實(shí)現(xiàn)新產(chǎn)品,直接修改工廠類,不需要再原客戶端代碼,更容易擴(kuò)展.
缺點(diǎn):
違背“開閉原則”:增加新產(chǎn)品時(shí)還需要修改工廠類代碼.
1.1.2、靜態(tài)工廠(擴(kuò)展)
在實(shí)際的開發(fā)中也有一部分人將工廠類中的創(chuàng)建對(duì)象的功能定義為靜態(tài)的,這個(gè)就是靜態(tài)工廠模式,避免對(duì)象的重復(fù)創(chuàng)建.? 他也不是屬于 23 中設(shè)計(jì)模式中的.
/**
* 簡(jiǎn)單工廠模式
*/
public class StaticCoffeeFactory {
public static Coffee createCoffee(String type) {
//1.根據(jù)訂單類型選取對(duì)應(yīng)的咖啡
Coffee coffee = null;
if (type == null || type.equals("")) {
throw new RuntimeException("type 非法");
} else if (type.equals("ac")) {
coffee = new AmericanCoffee();
} else if(type.equals("lc")) {
coffee = new LatteCoffee();
} else {
throw new RuntimeException("type 非法");
}
//2.加糖加量
coffee.addSugar();
coffee.addWeight();
return coffee;
}
}
1.1.3、工廠方法模式
概念
定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪個(gè)產(chǎn)品類對(duì)象。工廠方法使一個(gè)產(chǎn)品類的實(shí)例化延遲到其工廠的子類。
工廠方法模式包含以下角色:
- 抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過(guò)它訪問(wèn)具體工廠的工廠 方法來(lái)創(chuàng)建產(chǎn)品。
- 具體工廠(ConcreteFactory):主要是實(shí)現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
- 抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
- 具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來(lái)創(chuàng)建,它同 具體工廠之間一一對(duì)應(yīng)。
案例
需求:設(shè)計(jì)一個(gè)咖啡店點(diǎn)餐系統(tǒng),咖啡種類有美式咖啡和拿鐵咖啡.
/**
* 抽象產(chǎn)品: 咖啡類
*/
public abstract class Coffee {
public abstract String getName();
public void addSugar() {
System.out.println("加糖");
}
public void addWeight() {
System.out.println("加量");
}
}
/**
* 具體產(chǎn)品:美式咖啡類
*/
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
/**
* 具體產(chǎn)品:拿鐵咖啡類
*/
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿鐵咖啡";
}
}
/**
* 抽象工廠: 咖啡工廠
*/
public interface CoffeeFactory {
Coffee createCoffee();
}
/**
* 具體工廠:美式咖啡工廠
*/
public class AmericanCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
/**
* 具體工廠:拿鐵咖啡工廠
*/
public class LatteCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
}
/**
* 咖啡商店
*/
public class CoffeeStore {
private CoffeeFactory factory;
public void setFactory(CoffeeFactory factory) {
this.factory = factory;
}
public Coffee orderCoffee() {
//1.創(chuàng)建咖啡對(duì)象
Coffee coffee = factory.createCoffee();
//2.加料
coffee.addWeight();
coffee.addSugar();
return coffee;
}
}
public class ClientCoffee {
public static void main(String[] args) {
CoffeeStore store = new CoffeeStore();
// AmericanCoffeeFactory factory = new AmericanCoffeeFactory();
LatteCoffeeFactory factory = new LatteCoffeeFactory();
store.setFactory(factory);
Coffee coffee = store.orderCoffee();
System.out.println(coffee.getName());
}
}
優(yōu)點(diǎn):
使用便利:用戶只需要知道具體的工廠名稱就可以拿到產(chǎn)品,無(wú)須知道產(chǎn)品的具體創(chuàng)建過(guò)程.
滿足“開閉原則”:當(dāng)需要添加新的產(chǎn)品時(shí),無(wú)需對(duì)原工廠進(jìn)行修改,只需要添加具體的產(chǎn)品類和工廠即可.
缺點(diǎn):
“類爆炸”:每增加一個(gè)產(chǎn)品就需要增加一個(gè)具體產(chǎn)品類和一個(gè)對(duì)應(yīng)的具體工廠類,增加系統(tǒng)復(fù)雜度.
使用場(chǎng)景:
- 重復(fù)代碼 :?創(chuàng)建對(duì)象需要使用大量重復(fù)的代碼 ;
- 不關(guān)心創(chuàng)建過(guò)程 :?客戶端?不依賴 產(chǎn)品類?,?不關(guān)心 實(shí)例 如何被創(chuàng)建 , 實(shí)現(xiàn)等細(xì)節(jié) ;
- 創(chuàng)建對(duì)象 :?一個(gè)類通過(guò)其子類來(lái)指定創(chuàng)建哪個(gè)對(duì)象 ;
1.2、建造者模式
1.2.1、概念
將一個(gè)復(fù)雜對(duì)象分解成多個(gè)相對(duì)簡(jiǎn)單的部分,然后根據(jù)不同需要分別創(chuàng)建它們,最后構(gòu)建成該復(fù)雜對(duì)象。例如電腦的主機(jī)由 cpu、內(nèi)存、主板、顯卡 構(gòu)成,用戶只需要指定主機(jī)的類型就可以得到相應(yīng)的主機(jī),無(wú)需知道內(nèi)部的具體構(gòu)造細(xì)節(jié).
建造者模式包含如下角色:
- 抽象建造者類(Builder):這個(gè)接口規(guī)定要實(shí)現(xiàn)復(fù)雜對(duì)象的那些部分的創(chuàng)建,并不涉及具體的部件對(duì)象的創(chuàng)建。
- 具體建造者類(ConcreteBuilder):實(shí)現(xiàn) Builder 接口,完成復(fù)雜產(chǎn)品的各個(gè)部件的具體 創(chuàng)建方法。在構(gòu)造過(guò)程完成后,提供產(chǎn)品的實(shí)例。
- 產(chǎn)品類(Product):要?jiǎng)?chuàng)建的復(fù)雜對(duì)象。
- 指揮者類(Director):調(diào)用具體建造者來(lái)創(chuàng)建復(fù)雜對(duì)象的各個(gè)部分,在指導(dǎo)者中不涉及具體產(chǎn) 品的信息,只負(fù)責(zé)保證對(duì)象各部分完整創(chuàng)建或按某種順序創(chuàng)建。
1.2.2、案例
生產(chǎn)自行車是一個(gè)復(fù)雜的過(guò)程,它包含了車架,車座等組件的生產(chǎn)。而車架又有碳纖維,鋁合金等材質(zhì) 的,車座有橡膠,真皮等材質(zhì)。對(duì)于自行車的生產(chǎn)就可以使用建造者模式。
/**
* 產(chǎn)品類:自行車類
*/
public class Bike {
//車架
private String frame;
//車座
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
/**
* 抽象建造者類
*/
public abstract class Builder {
//這里只是一個(gè)空架子,還需要具體實(shí)現(xiàn)
protected Bike bike = new Bike();
//自行車的組成部分
public abstract void buildFrame();
public abstract void buildSeat();
//構(gòu)建自行車
public abstract Bike createBike();
}
/**
* 具體建造者類:捷安特建造者類
*/
public class GiantBuilder extends Builder{
@Override
public void buildFrame() {
this.bike.setFrame("碳纖維車架");
}
@Override
public void buildSeat() {
this.bike.setSeat("橡膠車座");
}
@Override
public Bike createBike() {
return this.bike;
}
}
/**
* 具體建造者類:摩拜建造者類
*/
public class MobikeBuilder extends Builder {
@Override
public void buildFrame() {
this.bike.setFrame("鋁合金車架");
}
@Override
public void buildSeat() {
this.bike.setSeat("真皮車座");
}
@Override
public Bike createBike() {
return this.bike;
}
}
/**
* 指揮者類
*/
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
/**
* 指導(dǎo)構(gòu)造
* @return
*/
public Bike construct() {
//開始構(gòu)建
builder.buildFrame();
builder.buildSeat();
return builder.createBike();
}
}
/**
* 測(cè)試類
*/
public class Client {
public static void main(String[] args) {
//建造捷安特自行車
showBike(new GiantBuilder());
//建造摩拜自行車
showBike(new MobikeBuilder());
}
private static void showBike(Builder builder) {
Director director = new Director(builder);
Bike bike = director.construct();
System.out.println(bike.getFrame());
System.out.println(bike.getSeat());
}
}
優(yōu)點(diǎn):
解耦合:客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過(guò)程解耦,使得 相同的創(chuàng)建過(guò)程可以創(chuàng)建不同的產(chǎn)品對(duì)象。
易擴(kuò)展,符合開閉原則:如果有新的需求,通過(guò)實(shí)現(xiàn)一個(gè)新的建造者就可以完成,基本上不用修改其他代碼.
缺點(diǎn):
如果產(chǎn)品之間的差異性比較大,則不適合使用,因此使用范圍受到一定的限制.
使用場(chǎng)景:
創(chuàng)建對(duì)象的過(guò)程比較負(fù)責(zé),由多個(gè)部件構(gòu)成,但構(gòu)建的順序是穩(wěn)定的.
產(chǎn)品的構(gòu)建過(guò)程和最終的表示是獨(dú)立的.
1.2.3、建造者模式擴(kuò)展:鏈?zhǔn)骄幊痰讓?/h4>
建造者模式除了上述用途以外,在開發(fā)中還有一種常用的使用方式,就是當(dāng)一個(gè)類構(gòu)造器需要傳入多個(gè)參數(shù),此時(shí)創(chuàng)建這個(gè)類的實(shí)例,代碼的可讀性就會(huì)非常差,而且很容易引入新的錯(cuò)誤. 此時(shí)就可以使用 鏈?zhǔn)骄幊痰讓?的方式對(duì) 建造者模式進(jìn)行重構(gòu).
?重構(gòu)后代碼如下:
public class Phone {
private String cpu;
private String screen;
private String memory;
private String mainBoard;
//私有構(gòu)造,只對(duì)內(nèi)提供
private Phone(Builder builder) {
this.cpu = builder.cpu;
this.screen = builder.screen;
this.memory = builder.memory;
this.mainBoard = builder.mainBoard;
}
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", memory='" + memory + '\'' +
", mainBoard='" + mainBoard + '\'' +
'}';
}
//鏈?zhǔn)骄幊虡?gòu)建
public static class Builder {
private String cpu;
private String screen;
private String memory;
private String mainBoard;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder screen(String screen) {
this.screen = screen;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Builder mainBoard(String mainBoard) {
this.mainBoard = mainBoard;
return this;
}
public Phone build() {
return new Phone(this);
}
}
}
public class Client {
public static void main(String[] args) {
Phone phone = new Phone.Builder()
.cpu("intel")
.screen("三星屏幕")
.mainBoard("華碩")
.memory("金士頓")
.build();
System.out.println(phone);
}
}
重構(gòu)后使用起來(lái)更加方便,提高開發(fā)效率.? 但是從軟件設(shè)計(jì)上,對(duì)程序員的要求比較高.
1.3、工廠方法模式 VS 建造者模式
工廠方法模式注重是整體對(duì)象的創(chuàng)建方式;而建造者模式注重的是部件一步一步的創(chuàng)建出一個(gè)復(fù)雜對(duì)象的過(guò)程 .
比如我要制造一個(gè)超人,如果使用工廠方法模式,直接產(chǎn)生出來(lái)就是一個(gè)力大無(wú)窮、能飛,內(nèi)褲外穿的超人;而如果使用建造者模式,則需要組裝 手、頭、腳、軀干、褲頭... 一個(gè)超人就誕生了.文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-726711.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-726711.html
到了這里,關(guān)于設(shè)計(jì)模式 - 創(chuàng)建型模式考點(diǎn)篇:工廠模式、建造者模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!