設計模式中的建立類模式
建立類模式包括工廠方法模式、建造者模式、抽象工廠模式、單例模式和原型模式。
- 單例模式:要保持在記憶體中隻有一個對象。
- 原型模式:要求通過複制的方式産生一個新的對象。實作Cloneable接口,并覆寫和重寫clone()方法。克隆。
- 工廠方法模式:注重的是整體對象的建立方法,用一個類封裝特定産品的執行個體化,即把new進行封裝。
- 建造者模式:注重的是部件建構的過程。先使用一個類對産品進行組裝,然後再使用導演類對其封裝。
- 抽象工廠模式:不需要關心建構過程,隻關心什麼産品由什麼工廠生産。
工廠方法模式 VS 建造者模式
差別
(1)意圖不同:
- 工廠方法模式,關注的是一個産品整體;
- 建造者模式,關注的是産品各個部件的産生以及裝配順序。
(2)産品的複雜度不同:
- 工廠方法模式建立的産品一般都是單一性質産品,都是一個模樣;
- 建造者模式建立的是一個複合産品,它由各個部件複合而成,部件不同産品對象不同。
工廠方法模式的對象粒度比較粗,建造者模式的産品對象粒度比較細。
例如
如要制造一個超人,如果使用工廠方法模式,直接産生出來的就是一個力大無窮、能夠飛翔、内褲外穿的超人;而如果使用建造者模式,則需要組裝手、頭、腳、軀幹等部分,然後再把内褲外穿,才會産生一個超人。
(1)工廠方法模式建造超人

public interface ISuperMan {
//每個超人都有特殊技能
public void specialTalent();
}
public class AdultSuperMan implements ISuperMan { //成年超人
public void specialTalent() {
System.out.println("超人力大無窮");
}
}
public class ChildSuperMan implements ISuperMan { //未成年超人
public void specialTalent() {
System.out.println("小超人的能力是刀槍不入、快速運動");
}
}
public class SuperManFactory {
//定義一個生産超人的工廠
public static ISuperMan createSuperMan(String type){
//根據輸入參數産生不同的超人
if(type.equalsIgnoreCase("adult")){
return new AdultSuperMan();
}else if(type.equalsIgnoreCase("child")){
return new ChildSuperMan();
}else{
return null;
}
}
}
public class Client {
public static void main(String[] args) {
//生産一個成年超人
ISuperMan adultSuperMan = SuperManFactory.createSuperMan("adult");
//展示一下超人的技能
adultSuperMan.specialTalent();
}
}
注意:通過工廠方法模式生産出對象,然後由用戶端進行對象的其他操作,但是并不代表所有生産出的對象都必須具有相同的狀态和行為,它是由産品所決定。
(2)建造者模式建造超人
public class SuperMan {
//超人的軀體
private String body;
//超人的特殊技能
private String specialTalent;
//超人的标志
private String specialSymbol;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getSpecialTalent() {
return specialTalent;
}
public void setSpecialTalent(String specialTalent) {
this.specialTalent = specialTalent;
}
public String getSpecialSymbol() {
return specialSymbol;
}
public void setSpecialSymbol(String specialSymbol) {
this.specialSymbol = specialSymbol;
}
}
public abstract class Builder {
//定義一個超人的應用
protected final SuperMan superMan = new SuperMan();
//建構出超人的軀體
public void setBody(String body){
this.superMan.setBody(body);
}
//建構出超人的特殊技能
public void setSpecialTalent(String st){
this.superMan.setSpecialTalent(st);
}
//建構出超人的特殊标記
public void setSpecialSymbol(String ss){
this.superMan.setSpecialSymbol(ss);
}
//建構出一個完整的超人
public abstract SuperMan getSuperMan();
}
public class AdultSuperManBuilder extends Builder {
@Override
public SuperMan getSuperMan() {
super.setBody("強壯的軀體");
super.setSpecialTalent("會飛行");
super.setSpecialSymbol("胸前帶S标記");
return super.superMan;
}
}
public class ChildSuperManBuilder extends Builder {
@Override
public SuperMan getSuperMan() {
super.setBody("強壯的軀體");
super.setSpecialTalent("刀槍不入");
super.setSpecialSymbol("胸前帶小S标記");
return super.superMan;
}
}
public class Director {
//兩個建造者的應用
private static Builder adultBuilder = new AdultSuperManBuilder();
//未成年超人的建造者
private static Builder childBuilder = new ChildSuperManBuilder();
//建造一個成年、會飛行的超人
public static SuperMan getAdultSuperMan(){
return adultBuilder.getSuperMan();
}
//建造一個未成年、刀槍不入的超人
public static SuperMan getChildSuperMan(){
return childBuilder.getSuperMan();
}
}
public class Client {
public static void main(String[] args) {
//建造一個成年超人
SuperMan adultSuperMan = Director.getAdultSuperMan();
//展示一下超人的資訊
adultSuperMan.getSpecialTalent();
}
}
建造者必須關注超人的各個部件,而工廠方法模式則隻關注超人的整體,這就是兩者的差別。
抽象工廠模式 VS 建造者模式
差別
- 如果希望屏蔽對象的建立過程,隻提供一個封裝良好的對象,則可以選擇抽象工廠方法模式。
- 而建造者模式可以用在構件的裝配方面,如通過裝配不同的元件或者相同元件的不同順序,可以産生出一個新的對象,它可以産生一個非常靈活的架構,友善地擴充和維護系統。
例如
現代化的汽車工廠能夠批量生産汽車。不同的工廠生産不同的汽車,寶馬工廠生産寶馬牌子的車,奔馳工廠生産奔馳牌子的車。車不僅具有不同品牌,還有不同的用途分類,如商務車Van,運動型車SUV等,我們按照兩種設計模式分别實作車輛的生産過程。
(1)抽象工廠模式生産車輛
public interface ICar {
//汽車的生産商,也就是牌子
public String getBand();
//汽車的型号
public String getModel();
}
public abstract class AbsBMW implements ICar {
private final static String BMW_BAND = "寶馬汽車";
//寶馬車
public String getBand() {
return BMW_BAND;
}
//型号由具體的實作類實作
public abstract String getModel();
}
public class BMWVan extends AbsBMW {
private final static String SEVENT_SEARIES = "7系列車型商務車";
public String getModel() {
return SEVENT_SEARIES;
}
}
public class BMWSuv extends AbsBMW {
private final static String X_SEARIES = "X系列車型SUV";
public String getModel() {
return X_SEARIES;
}
}
public abstract class AbsBenz implements ICar {
private final static String BENZ_BAND = "奔馳汽車";
public String getBand() {
return BENZ_BAND;
}
//具體型号由實作類完成
public abstract String getModel();
}
public class BenzVan extends AbsBenz {
private final static String R_SERIES = "R系列商務車";
public String getModel() {
return R_SERIES;
}
}
public class BenzSuv extends AbsBenz {
private final static String G_SERIES = "G系列SUV";
public String getModel() {
return G_SERIES;
}
}
public interface CarFactory {
//生産SUV
public ICar createSuv();
//生産商務車
public ICar createVan();
}
public class BMWFactory implements CarFactory {
//生産SUV
public ICar createSuv() {
return new BMWSuv();
}
//生産商務車
public ICar createVan(){
return new BMWVan();
}
}
public class BenzFactory implements CarFactory {
//生産SUV
public ICar createSuv() {
return new BenzSuv();
}
//生産商務車
public ICar createVan(){
return new BenzVan();
}
}
public class Client {
public static void main(String[] args) {
//要求生産一輛奔馳SUV
System.out.println("===要求生産一輛奔馳SUV===");
//首先找到生産奔馳車的工廠
System.out.println("A、找到奔馳車工廠");
CarFactory carFactory= new BenzFactory();
//開始生産奔馳SUV
System.out.println("B、開始生産奔馳SUV");
ICar benzSuv = carFactory.createSuv();
//生産完畢,展示一下車輛資訊
System.out.println("C、生産出的汽車如下:");
System.out.println("汽車品牌:"+benzSuv.getBand());
System.out.println("汽車型号:" + benzSuv.getModel());
}
}
(2)建造者模式生産車輛
建造者模式需要把車輛進行拆分,拆分成引擎和車輪兩部分,然後由建造者根據設計圖紙制造車。它注重的是對零件的裝配、組合、封裝,從一個細微構件裝配角度看待一個對象。
public interface ICar {
//汽車車輪
public String getWheel();
//汽車引擎
public String getEngine();
}
public class Car implements ICar {
//汽車引擎
private String engine;
//汽車車輪
private String wheel;
//一次性傳遞汽車需要的資訊
public Car(String _engine,String _wheel){
this.engine = _engine;
this.wheel = _wheel;
}
public String getEngine() {
return engine;
}
public String getWheel() {
return wheel;
}
public String toString(){
return "車的輪子是:" + wheel + "\n車的引擎是:" + engine;
}
}
public abstract class CarBuilder {
//待建造的汽車
private ICar car;
//設計藍圖
private Blueprint bp;
public Car buildCar(){
//按照順序生産一輛車
return new Car(buildEngine(),buildWheel());
}
//接收一份設計藍圖
public void receiveBlueprint(Blueprint _bp){
this.bp = _bp;
}
//檢視藍圖,隻有真正的建造者才可以檢視藍圖
protected Blueprint getBlueprint(){
return bp;
}
//建造車輪
protected abstract String buildWheel();
//建造引擎
protected abstract String buildEngine();
}
public class Blueprint {
//車輪的要求
private String wheel;
//引擎的要求
private String engine;
public String getWheel() {
return wheel;
}
public void setWheel(String wheel) {
this.wheel = wheel;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
}
這和一個具體的産品Car類是不一樣的,它是一個藍圖,有一個藍圖可以設計出非常多的産品,如有一個R系統的奔馳商務車設計藍圖,我們就可以生産出一系列的奔馳車。它指導我們的産品生産,而不是一個具體的産品。
public class BMWBuilder extends CarBuilder {
public String buildEngine() {
return super.getBlueprint().getEngine();
}
public String buildWheel() {
return super.getBlueprint().getWheel();
}
}
public class BenzBuilder extends CarBuilder {
public String buildEngine() {
return super.getBlueprint().getEngine();
}
public String buildWheel() {
return super.getBlueprint().getWheel();
}
}
public class Director {
//聲明對建造者的引用
private CarBuilder benzBuilder = new BenzBuilder();
private CarBuilder bmwBuilder = new BMWBuilder();
//生産奔馳SUV
public ICar createBenzSuv(){
//制造出汽車
return createCar(benzBuilder, "benz的引擎", "benz的輪胎");
}
//生産出一輛寶馬商務車
public ICar createBMWVan(){
return createCar(benzBuilder, "BMW的引擎", "BMW的輪胎");
}
//生産出一個混合車型
public ICar createComplexCar(){
return createCar(bmwBuilder, "BMW的引擎", "benz的輪胎");
}
//生産車輛
private ICar createCar(CarBuilder _carBuilder,String engine,String wheel){
//導演懷揣藍圖
Blueprint bp = new Blueprint();
bp.setEngine(engine);
bp.setWheel(wheel);
System.out.println("獲得生産藍圖");
_carBuilder.receiveBlueprint(bp);
return _carBuilder.buildCar();
}
}
public class Client {
public static void main(String[] args) {
//定義出導演類
Director director =new Director();
//給我一輛奔馳車SUV
System.out.println("===制造一輛奔馳SUV===");
ICar benzSuv = director.createBenzSuv();
System.out.println(benzSuv);
//給我一輛寶馬商務車
System.out.println("\n===制造一輛寶馬商務車===");
ICar bmwVan = director.createBMWVan();
System.out.println(bmwVan);
//給我一輛混合車型
System.out.println("\n===制造一輛混合車===");
ICar complexCar = director.createComplexCar();
System.out.println(complexCar);
}
}