假如产品之间有可以负责联系的元素,那依赖该元素找出共同点後建立关联,进而减少工厂的数量,却可以维持更多的生产。
昨天提到 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 模式。
>>: [Day 07] 使用 fastAPI 部署 YOLOv4 (1/2) — 以内建 Client 进行互动
使用 atlantis 做 terraform automation,Terraform Remot...
前言: 今天来介绍使用Canvas 的绘图方法来创建 2D 绘图,并画出触控手势的轨迹。 大纲 : ...
环境 Windows 10 21H1 System Monitor v13.01 前情提要 在【Da...
不知不觉,铁人赛慢慢要进入尾声了,感谢过程中队友们彼此提携,互相提醒。 在前几天中,和大家介绍了 D...
大家好 我刚接触RouterOS没多久 因为内网有电脑在架SERVER 必须开 PORT 映射 所以...