假如產品之間有可以負責聯繫的元素,那依賴該元素找出共同點後建立關聯,進而減少工廠的數量,卻可以維持更多的生產。
昨天提到 Factory Method,建立許多工廠來負責生產產品。讓我們試想一個情境,現在行銷部門決定要建立多種口味的飲料,因此會有櫻桃口味、檸檬口味與加鹽,套用在現有的三個產品(可樂、礦泉水、柳橙汁),會有九種結果,此時,必須建立多達九個的 Factory 來處理這件事。
可樂 | 礦泉水 | 柳橙汁 | |
---|---|---|---|
櫻桃口味 | 櫻桃口味可樂 | 人工櫻桃風味礦泉水 | 櫻桃柳橙汁 |
檸檬口味 | 檸檬口味可樂 | 檸檬礦泉水 | 檸檬柳橙汁 |
加鹽 | 加鹽可樂 | 加鹽礦泉水 | 加鹽柳橙汁 |
此時,可以使用 Abstract Factory 減少工廠的數量,作法是:
Abstract Class
、Interface
。Abstract Class
、Interface
,負責要求每間口味工廠需要生產三種原有產品。產品祖代:PETBottle
public abstract class PETBottle {
protected String smell = "";
protected String color = "";
protected PETBottle(String smell, String color) {
this.smell = smell;
this.color = color;
}
public abstract String getTaste();
}
產品親代-可樂:Coke
public abstract class Coke extends PETBottle {
protected Coke(String smell) {
super(smell, "黑色");
}
@Override
public String getTaste() {
return "這瓶可樂的顏色:" + color + ",香味是:" + smell;
}
}
產品子代-可樂相關口味系列:CherryCoke
、LemonCoke
、SaltCoke
public class CherryCoke extends Coke {
public CherryCoke() {
super("櫻桃味道");
}
@Override
public String getTaste() {
return "這瓶櫻桃可樂的顏色:" + color + ",香味是:" + smell;
}
}
public class LemonCoke extends Coke {
public LemonCoke() {
super("清新的酸味");
}
@Override
public String getTaste() {
return "這瓶檸檬可樂的顏色:" + color + ",香味是:" + smell;
}
}
public class SaltCoke extends Coke {
public SaltCoke() {
super("鹹鹹的");
}
@Override
public String getTaste() {
return "這瓶加鹽可樂的顏色:" + color + ",香味是:" + smell;
}
}
產品親代-礦泉水:Water
public abstract class Water extends PETBottle {
protected Water(String smell) {
super(smell, "透明");
}
@Override
public String getTaste() {
return "這瓶水的顏色:" + color + ",香味是:" + smell;
}
}
產品子代-礦泉水相關口味系列:CherryWater
、LemonWater
、SaltWater
public class CherryWater extends Water {
public CherryWater() {
super("櫻桃味道");
}
@Override
public String getTaste() {
return "這瓶人工櫻桃風味礦泉水的顏色:" + color + ",香味是:" + smell;
}
}
public class LemonWater extends Water {
public LemonWater() {
super("清新的酸味");
}
@Override
public String getTaste() {
return "這瓶檸檬礦泉水的顏色:" + color + ",香味是:" + smell;
}
}
public class SaltWater extends Water {
public SaltWater() {
super("鹹鹹的");
}
@Override
public String getTaste() {
return "這瓶加鹽礦泉水的顏色:" + color + ",香味是:" + smell;
}
}
產品親代-柳橙汁:OrangeJuice
public abstract class OrangeJuice extends PETBottle {
protected OrangeJuice(String smell) {
super(smell, "橘色");
}
@Override
public String getTaste() {
return "這瓶柳橙汁的顏色:" + color + ",香味是:" + smell;
}
}
產品子代-柳橙汁相關口味系列:CherryOrangeJuice
、LemonOrangeJuice
、SaltOrangeJuice
public class CherryOrangeJuice extends OrangeJuice {
public CherryOrangeJuice() {
super("櫻桃味道");
}
@Override
public String getTaste() {
return "這瓶櫻桃柳橙汁的顏色:" + color + ",香味是:" + smell;
}
}
public class LemonOrangeJuice extends OrangeJuice {
public LemonOrangeJuice() {
super("柑橘類特有的酸味");
}
@Override
public String getTaste() {
return "這瓶檸檬柳橙汁的顏色:" + color + ",香味是:" + smell;
}
}
public class SaltOrangeJuice extends OrangeJuice {
public SaltOrangeJuice() {
super("鹹鹹的");
}
@Override
public String getTaste() {
return "這瓶加鹽柳橙汁的顏色:" + color + ",香味是:" + smell;
}
}
工廠親代:BeverageFactory
public interface BeverageFactory {
Coke produceCoke();
Water produceWater();
OrangeJuice produceOrangeJuice();
}
工廠子代-相關口味系列:CherryFlavorFactory
、LemonFlavorFactory
、SaltFlavorFactory
public class CherryFlavorFactory implements BeverageFactory {
@Override
public Coke produceCoke() {
return new CherryCoke();
}
@Override
public Water produceWater() {
return new CherryWater();
}
@Override
public OrangeJuice produceOrangeJuice() {
return new CherryOrangeJuice();
}
}
public class LemonFlavorFactory implements BeverageFactory {
@Override
public Coke produceCoke() {
return new LemonCoke();
}
@Override
public Water produceWater() {
return new LemonWater();
}
@Override
public OrangeJuice produceOrangeJuice() {
return new LemonOrangeJuice();
}
}
public class SaltFlavorFactory implements BeverageFactory {
@Override
public Coke produceCoke() {
return new SaltCoke();
}
@Override
public Water produceWater() {
return new SaltWater();
}
@Override
public OrangeJuice produceOrangeJuice() {
return new SaltOrangeJuice();
}
}
決策者:
public class BeverageAbstractFactorySample {
public static void main(String[] args) {
System.out.println("準備開喝!");
BeverageFactory saltFlavorFactory = new SaltFlavorFactory();
Coke saltCoke = saltFlavorFactory.produceCoke();
Water saltWater = saltFlavorFactory.produceWater();
OrangeJuice saltOrangeJuice = saltFlavorFactory.produceOrangeJuice();
System.out.println("鹽味派對!");
System.out.println(saltCoke.getTaste());
System.out.println(saltWater.getTaste());
System.out.println(saltOrangeJuice.getTaste());
System.out.println("\n口味更換");
BeverageFactory lemonFlavorFactory = new LemonFlavorFactory();
Coke lemonCoke = lemonFlavorFactory.produceCoke();
Water lemonWater = lemonFlavorFactory.produceWater();
OrangeJuice lemonOrangeJuice = lemonFlavorFactory.produceOrangeJuice();
System.out.println("檸檬派對!");
System.out.println(lemonCoke.getTaste());
System.out.println(lemonWater.getTaste());
System.out.println(lemonOrangeJuice.getTaste());
System.out.println("\n最後一輪");
BeverageFactory cherryFlavorFactory = new CherryFlavorFactory();
Coke cherryCoke = cherryFlavorFactory.produceCoke();
Water cherryWater = cherryFlavorFactory.produceWater();
OrangeJuice cherryOrangeJuice = cherryFlavorFactory.produceOrangeJuice();
System.out.println("櫻桃派對!");
System.out.println(cherryCoke.getTaste());
System.out.println(cherryWater.getTaste());
System.out.println(cherryOrangeJuice.getTaste());
}
}
受限於 JavaScript 沒有虛擬型別、無法限制型別。
產品祖代:PETBottle
/** @abstract */
class PETBottle {
constructor(smell, color) {
this.smell = smell;
this.color = color;
}
getTaste() { return; }
}
產品親代-可樂:Coke
/** @abstract */
class Coke extends PETBottle {
constructor(smell, color) {
super(smell, "黑色");
}
/** @override */
getTaste() {
return "這瓶可樂的顏色:" + this.color + ",香味是:" + this.smell;
}
}
產品子代-可樂相關口味系列:CherryCoke
、LemonCoke
、SaltCoke
class CherryCoke extends Coke {
constructor() {
super("櫻桃風味");
}
/** @override */
getTaste() {
return "這瓶櫻桃可樂的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class LemonCoke extends Coke {
constructor() {
super("清新的酸味");
}
/** @override */
getTaste() {
return "這瓶檸檬可樂的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class SaltCoke extends Coke {
constructor() {
super("鹹鹹的");
}
/** @override */
getTaste() {
return "這瓶加鹽可樂的顏色:" + this.color + ",香味是:" + this.smell;
}
}
產品親代-礦泉水:Water
/** @abstract */
class Water extends PETBottle {
constructor(smell) {
super(smell, "透明");
}
/** @override */
getTaste() {
return "這瓶水的顏色:" + this.color + ",香味是:" + this.smell;
}
}
產品子代-礦泉水相關口味系列:CherryWater
、LemonWater
、SaltWater
class CherryWater extends Water {
constructor() {
super("櫻桃味道");
}
/** @override */
getTaste() {
return "這瓶人工櫻桃風味礦泉水的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class LemonWater extends Water {
constructor() {
super("清新的酸味");
}
/** @override */
getTaste() {
return "這瓶檸檬礦泉水的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class SaltWater extends Water {
constructor() {
super("鹹鹹的");
}
/** @override */
getTaste() {
return "這瓶加鹽礦泉水的顏色:" + this.color + ",香味是:" + this.smell;
}
}
產品親代-柳橙汁:OrangeJuice
/** @abstract */
class OrangeJuice extends PETBottle {
constructor(smell) {
super(smell, "橘色");
}
/** @override */
getTaste() {
return "這瓶柳橙汁的顏色:" + this.color + ",香味是:" + this.smell;
}
}
產品子代-柳橙汁相關口味系列:CherryOrangeJuice
、LemonOrangeJuice
、SaltOrangeJuice
class CherryOrangeJuice extends OrangeJuice {
constructor() {
super("櫻桃味道");
}
/** @override */
getTaste() {
return "這瓶櫻桃柳橙汁的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class LemonOrangeJuice extends OrangeJuice {
constructor() {
super("柑橘類特有的酸味");
}
/** @override */
getTaste() {
return "這瓶檸檬柳橙汁的顏色:" + this.color + ",香味是:" + this.smell;
}
}
class SaltOrangeJuice extends OrangeJuice {
constructor() {
super("鹹鹹的");
}
/** @override */
getTaste() {
return "這瓶加鹽柳橙汁的顏色:" + this.color + ",香味是:" + this.smell;
}
}
工廠親代:BeverageFactory
/** @interface */
class BeverageFactory {
produceCoke() { return; }
produceWater() { return; }
produceOrangeJuice() { return; }
}
工廠子代-相關口味系列:CherryFlavorFactory
、LemonFlavorFactory
、SaltFlavorFactory
class CherryFlavorFactory extends BeverageFactory {
/** @override */
produceCoke() {
return new CherryCoke();
}
/** @override */
produceWater() {
return new CherryWater();
}
/** @override */
produceOrangeJuice() {
return new CherryOrangeJuice();
}
}
class LemonFlavorFactory extends BeverageFactory {
/** @override */
produceCoke() {
return new LemonCoke();
}
/** @override */
produceWater() {
return new LemonWater();
}
/** @override */
produceOrangeJuice() {
return new LemonOrangeJuice();
}
}
class SaltFlavorFactory extends BeverageFactory {
/** @override */
produceCoke() {
return new SaltCoke();
}
/** @override */
produceWater() {
return new SaltWater();
}
/** @override */
produceOrangeJuice() {
return new SaltOrangeJuice();
}
}
實作:
const beverageAbstractFactorySample = () => {
console.log("準備開喝!");
const saltFlavorFactory = new SaltFlavorFactory();
const saltCoke = saltFlavorFactory.produceCoke();
const saltWater = saltFlavorFactory.produceWater();
const saltOrangeJuice = saltFlavorFactory.produceOrangeJuice();
console.log("鹽味派對!");
console.log(saltCoke.getTaste());
console.log(saltWater.getTaste());
console.log(saltOrangeJuice.getTaste());
console.log("\n口味更換");
const lemonFlavorFactory = new LemonFlavorFactory();
const lemonCoke = lemonFlavorFactory.produceCoke();
const lemonWater = lemonFlavorFactory.produceWater();
const lemonOrangeJuice = lemonFlavorFactory.produceOrangeJuice();
console.log("檸檬派對!");
console.log(lemonCoke.getTaste());
console.log(lemonWater.getTaste());
console.log(lemonOrangeJuice.getTaste());
console.log("\n最後一輪");
const cherryFlavorFactory = new CherryFlavorFactory();
const cherryCoke = cherryFlavorFactory.produceCoke();
const cherryWater = cherryFlavorFactory.produceWater();
const cherryOrangeJuice = cherryFlavorFactory.produceOrangeJuice();
console.log("櫻桃派對!");
console.log(cherryCoke.getTaste());
console.log(cherryWater.getTaste());
console.log(cherryOrangeJuice.getTaste());
};
beverageAbstractFactorySample();
Abstract Factory 改善了 Factory Method 面對更多種產品時,必須建立各自的工廠導致工廠數量過多的問題。當然,缺點也很明顯,「必須找到多種產品之間有沒有關聯」,如果有才能抽離、轉換成關係、建立工廠、減少數量;如果沒有則無計可施,只能維持 Factory Method 多工廠的局面。
三個 Factory 模式介紹完畢,接著依照字母順序,介紹 Builder 模式。