建造者的模式
定義:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示
使用場(chǎng)景:
1.多個(gè)部件或零件,都可以裝配到一個(gè)對(duì)象中,但產(chǎn)生的結(jié)果又不相同時(shí)。
2.當(dāng)初始化一個(gè)對(duì)象特別復(fù)雜的時(shí)候,比如參數(shù)多,而且很多參數(shù)都有默認(rèn)值。
它分為抽象建造者(Builder)角色、具體建造者(ConcreteBuilder)角色、導(dǎo)演者(Director)角色、產(chǎn)品(Product)角色四個(gè)角色。
抽象建造者(Builder)角色:給 出一個(gè)抽象接口,以規(guī)范產(chǎn)品對(duì)象的各個(gè)組成成分的建造。
具體建造者(ConcreteBuilder)角色:要完成的任務(wù)包括:1.實(shí)現(xiàn)抽象建造者Builder所聲明的接口,給出一步一步地完成創(chuàng)建產(chǎn)品實(shí)例的操作。2.在建造過程完成后,提供產(chǎn)品的實(shí)例。
導(dǎo)演者(Director)角色:擔(dān)任這個(gè)角色的類調(diào)用具體建造者角色以創(chuàng)建產(chǎn)品對(duì)象。
產(chǎn)品(Product)角色:產(chǎn)品便是建造中的復(fù)雜對(duì)象。
public interface Builder {
public Builder setName(String name);
public Builder setSex(boolean sex);
public Builder setAge(int age);
public Person create();
}
public class ConcreteBuilder implements Builder {
private String name;
private boolean sex;
private int age;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setSex(boolean sex) {
this.sex = sex;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Person create() {
return new Person(name, sex, age);
}
}
public class Director {
private Builder builder;
public Director(Builder builder){
this.builder = builder;
}
public void construct(String name, boolean sex, int age) {
builder.setName(name);
builder.setSex(sex);
builder.setAge(age);
}
}
public class Test {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director pcDirector = new Director(builder);
pcDirector.construct("zhangtao", true, 23);
Person person = builder.create();
}
}
工廠方法模式
定義:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪個(gè)類。
任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠方法模式。用new就能創(chuàng)建的對(duì)象不需要使用工廠模式,因?yàn)槭褂霉S模式就要增加一個(gè)工廠類,增加了系統(tǒng)復(fù)雜度。
關(guān)于工廠方法模式的實(shí)現(xiàn)
public abstract class Product {
public abstract void method();
}
public class ConcreteProductA extends Product {
@Override
public void method() {
System.out.println("產(chǎn)品A");
}
}
public abstract class Factory {
public abstract Product createProduct();
}
public class ConcreteFactory extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class Test {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.method();
}
}
當(dāng)確定工廠類只有一個(gè)的時(shí)候,簡(jiǎn)單工廠模式
public class Factory{
public static Product createProduct(){
return new ConcreteProductA();
}
}
工廠方法模式VS建造者模式
工廠方法模式注重的是整體對(duì)象的創(chuàng)建方法,而建造者模式注重的是部件構(gòu)建的過程,旨在通過一步一步地精確構(gòu)造創(chuàng)建出一個(gè)復(fù)雜的對(duì)象。
我們舉個(gè)簡(jiǎn)單例子來說明兩者的差異,如要制造一個(gè)超人,如果使用工廠方法模式,直接產(chǎn)生出來的就是一個(gè)力大無窮、能夠飛翔、內(nèi)褲外穿的超人;
而如果使用建造者模式,則需要組裝手、頭、腳、軀干等部分,然后再把內(nèi)褲外穿,于是一個(gè)超人就誕生了。
工廠方法模式創(chuàng)建的產(chǎn)品一般都是單一性質(zhì)產(chǎn)品,如成年超人,都是一個(gè)模樣,而建造者模式創(chuàng)建的則是一個(gè)復(fù)合產(chǎn)品,它由各個(gè)部件復(fù)合而成,部件不同產(chǎn)品對(duì)象當(dāng)然不同。
這不是說工廠方法模式創(chuàng)建的對(duì)象簡(jiǎn)單,而是指它們的粒度大小不同。一般來說,工廠方法模式的對(duì)象粒度比較粗,建造者模式的產(chǎn)品對(duì)象粒度比較細(xì)。
兩者的區(qū)別有了,那在具體的應(yīng)用中,我們?cè)撊绾芜x擇呢?
是用工廠方法模式來創(chuàng)建對(duì)象,還是用建造者模式來創(chuàng)建對(duì)象,這完全取決于我們?cè)谧鱿到y(tǒng)設(shè)計(jì)時(shí)的意圖,如果需要詳細(xì)關(guān)注一個(gè)產(chǎn)品部件的生產(chǎn)、安裝步驟,則選擇建造者,否則選擇工廠方法模式。
抽象工廠模式
定義:為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無須指定它們的具體類
public abstract class AbstractProductA {
//每個(gè)產(chǎn)品共有的方法
public void shareMethod(){
}
//每個(gè)產(chǎn)品相同方法,不同實(shí)現(xiàn)
public abstract void doSomething();
}
public class ProductA1 extends AbstractProductA {
public void doSomething() {
System.out.println("產(chǎn)品A1的實(shí)現(xiàn)方法");
}
}
public class ProductA2 extends AbstractProductA {
public void doSomething() {
System.out.println("產(chǎn)品A2的實(shí)現(xiàn)方法");
}
}
//抽象工廠類
public abstract class AbstractCreator {
//創(chuàng)建A產(chǎn)品家族
public abstract AbstractProductA createProductA();
//創(chuàng)建B產(chǎn)品家族
public abstract AbstractProductB createProductB();
}
public class Creator1 extends AbstractCreator {
//只生產(chǎn)產(chǎn)品等級(jí)為1的A產(chǎn)品
public AbstractProductA createProductA() {
return new ProductA1();
}
//只生產(chǎn)產(chǎn)品等級(jí)為1的B產(chǎn)品
public AbstractProductB createProductB() {
return new ProductB1();
}
}
public class Creator2 extends AbstractCreator {
//只生產(chǎn)產(chǎn)品等級(jí)為2的A產(chǎn)品
public AbstractProductA createProductA() {
return new ProductA2();
}
//只生產(chǎn)產(chǎn)品等級(jí)為2的B產(chǎn)品
public AbstractProductB createProductB() {
return new ProductB2();
}
}
public class Test {
public static void main(String[] args) {
//定義出兩個(gè)工廠
AbstractCreator creator1 = new Creator1();
AbstractCreator creator2 = new Creator2();
//產(chǎn)生A1對(duì)象
AbstractProductA a1 = creator1.createProductA();
//產(chǎn)生A2對(duì)象
AbstractProductA a2 = creator2.createProductA();
//產(chǎn)生B1對(duì)象
AbstractProductB b1 = creator1.createProductB();
//產(chǎn)生B2對(duì)象
AbstractProductB b2 = creator2.createProductB();
}
}
抽象工廠模式的使用場(chǎng)景定義非常簡(jiǎn)單:一個(gè)對(duì)象族(或是一組沒有任何關(guān)系的對(duì)象)都有相同的約束,則可以使用抽象工廠模式。
通過工廠類,只要知道工廠類是誰,我就能創(chuàng)建出一個(gè)需要的對(duì)象
注意事項(xiàng):
在抽象工廠模式的缺點(diǎn)中,我們提到抽象工廠模式的產(chǎn)品族擴(kuò)展比較困難,但是一定要清楚,是產(chǎn)品族擴(kuò)展困難,而不是產(chǎn)品等級(jí)。
在該模式下,產(chǎn)品等級(jí)是非常容易擴(kuò)展的,增加一個(gè)產(chǎn)品等級(jí),只要增加一個(gè)工廠類負(fù)責(zé)新增加出來的產(chǎn)品生產(chǎn)任務(wù)即可。
也就是說橫向擴(kuò)展容易,縱向擴(kuò)展困難。
抽象類AbstractCreator要增加一個(gè)方法createProductC(),然后兩個(gè)實(shí)現(xiàn)類都要修改,想想看,這嚴(yán)重違反了開閉原則。