不再限制一个工厂(物件)建立许多产品(物件),而是转变成一个产品(物件)对应一个工厂(物件),而决定生产哪个产品(物件)则转交给另一个决策者(物件)。
昨天提到,每次新增一个产品时,Simple Factory Method 内负责管理生产的工厂就必须「变动 switch-case
」,此项举动违反 SOLID 的 OCP。Factory Method 改良这一点,让每项产品拥有各自的工厂。实际决定要使用哪间工厂的决策者,则转交给其他物件负责,本身不涉入生产判定。
Factory Method 的作法是:
Class
、Abstract Class
或 Interface
。Interface
。产品亲代:PETBottle
public abstract class PETBottle {
protected String smell = "";
protected String color = "";
public PETBottle(String smell, String color) {
this.smell = smell;
this.color = color;
}
public abstract String getTaste();
}
产品子代:Coke
、Water
、OrangeJuice
public class Coke extends PETBottle {
public Coke(String smell, String color) {
super(smell, color);
}
@Override
public String getTaste() {
return "这瓶可乐的颜色:" + color + ",香味是:" + smell;
}
}
public class Water extends PETBottle {
public Water(String smell, String color) {
super(smell, color);
}
@Override
public String getTaste() {
return "这瓶水的颜色:" + color + ",香味是:" + smell;
}
}
public class OrangeJuice extends PETBottle {
public OrangeJuice(String smell, String color) {
super(smell, color);
}
@Override
public String getTaste() {
return "这瓶柳橙汁的颜色:" + color + ",香味是:" + smell;
}
}
工厂亲代:PETBottleFactory
public interface PETBottleFactory {
public PETBottle getPET_Bottle();
}
工厂子代:CokeFactory
、WaterFactory
、OrangeJuiceFactory
public class CokeFactory implements PETBottleFactory {
@Override
public PETBottle getPET_Bottle() {
System.out.println("机器选定可乐瓶子");
System.out.println("黑色液体冲入瓶子内");
System.out.println("转上瓶盖,完成");
return new Coke("甜甜的", "黑色");
}
}
public class OrangeJuiceFactory implements PETBottleFactory {
@Override
public PETBottle getPET_Bottle() {
System.out.println("机器选定矿泉柳橙汁瓶子");
System.out.println("橘色液体冲入瓶子内");
System.out.println("转上瓶盖,完成");
return new OrangeJuice("酸酸的", "橘色");
}
}
public class WaterFactory implements PETBottleFactory {
@Override
public PETBottle getPET_Bottle() {
System.out.println("机器选定矿泉水瓶子");
System.out.println("透明液体冲入瓶子内");
System.out.println("转上瓶盖,完成");
return new Water("无味", "透明的");
}
}
决策者:
public class PETBottleFactoryMethodSample {
public static void main(String[] args) {
System.out.println("今天我想来点,可乐!");
PETBottleFactory cokeFactory = new CokeFactory();
PETBottle coke = cokeFactory.getPET_Bottle();
System.out.println("得到一瓶可乐!");
System.out.println(coke.getTaste());
System.out.println("---咳咳咳---");
System.out.println("有点甜,我想喝点,矿泉水!");
PETBottleFactory waterFactory = new WaterFactory();
PETBottle water = waterFactory.getPET_Bottle();
System.out.println("得到一瓶矿泉水!");
System.out.println(water.getTaste());
System.out.println("---咕噜咕噜---");
System.out.println("清爽!最来来点,柳橙汁!");
PETBottleFactory orangeJuiceFactory = new OrangeJuiceFactory();
PETBottle orangeJuice = orangeJuiceFactory.getPET_Bottle();
System.out.println("得到一瓶柳橙汁!");
System.out.println(orangeJuice.getTaste());
}
}
受限於 JavaScript 没有虚拟型别、无法限制型别。
产品亲代:PETBottle
/** @abstract */
class PETBottle {
constructor(smell, color) {
this.smell = smell;
this.color = color;
}
getTaste() { return; }
}
产品子代:Coke
、Water
、OrangeJuice
class Coke extends PETBottle {
constructor(smell, color) {
super(smell, color);
}
/** @override */
getTaste() {
return "这瓶可乐的颜色:" + this.color + ",香味是:" + this.smell;
}
}
class Water extends PETBottle {
constructor(smell, color) {
super(smell, color);
}
/** @override */
getTaste() {
return "这瓶水的颜色:" + this.color + ",香味是:" + this.smell;
}
}
class OrangeJuice extends PETBottle {
constructor(smell, color) {
super(smell, color);
}
/** @override */
getTaste() {
return "这瓶柳橙汁的颜色:" + this.color + ",香味是:" + this.smell;
}
}
工厂亲代:PETBottleFactory
/** @interface */
class PETBottleFactory {
getPET_Bottle() { return; }
}
工厂子代:CokeFactory
、WaterFactory
、OrangeJuiceFactory
class CokeFactory extends PETBottleFactory {
/** @override */
getPET_Bottle() {
console.log("机器选定可乐瓶子");
console.log("黑色液体冲入瓶子内");
console.log("转上瓶盖,完成");
return new Coke("甜甜的", "黑色");
}
}
class WaterFactory extends PETBottleFactory {
/** @override */
getPET_Bottle() {
console.log("机器选定矿泉水瓶子");
console.log("透明液体冲入瓶子内");
console.log("转上瓶盖,完成");
return new Coke("甜甜的", "黑色");
}
}
class OrangeJuiceFactory extends PETBottleFactory {
/** @override */
getPET_Bottle() {
console.log("机器选定矿泉柳橙汁瓶子");
console.log("橘色液体冲入瓶子内");
console.log("转上瓶盖,完成");
return new OrangeJuice("酸酸的", "橘色");
}
}
决策者:
const PETBottleFactoryMethodSample = () => {
console.log("今天我想来点,可乐!");
const cokeFactory = new CokeFactory();
const coke = cokeFactory.getPET_Bottle();
console.log("得到一瓶可乐!");
console.log(coke.getTaste());
console.log("---咳咳咳---");
console.log("有点甜,我想喝点,矿泉水!");
const waterFactory = new WaterFactory();
const water = waterFactory.getPET_Bottle();
console.log("得到一瓶矿泉水!");
console.log(water.getTaste());
console.log("---咕噜咕噜---");
console.log("清爽!最来来点,柳橙汁!");
const orangeJuiceFactory = new OrangeJuiceFactory();
const orangeJuice = orangeJuiceFactory.getPET_Bottle();
console.log("得到一瓶柳橙汁!");
console.log(orangeJuice.getTaste());
};
PETBottleFactoryMethodSample();
Factory Method 改善了 Simple Factory Method 无法遵守 SOLID 的问题,将「选择」交给决策者,本身不涉及选择,只负责生产。
然而,这个生产是直线关系,工厂对应产品,假如生产的产品数量增加非常多时,整体程序会显得笨重、重复。此时,如果能找出产品之间的共通点,那就能抽离出来,重构後变成新的 Factory 模式。
明天,将介绍 Abstract Factory 模式。
<<: Day 06 : 操作基础篇 3 - 认识「主题」与 CSS 客制化设定
>>: [Day6] THM Basic Pentesting
在这边要介绍一下go的基本用法 而这些用法在A Tour of Go也都有介绍 在下面的程序码如果有...
「现在这个年代,带人要带心,公司架构尽量扁平化,跟同事打成一片最要紧。」 一个刚创业没多久的朋友跟我...
Git Flow 的缺点可以参考 git flow 实战经验谈 part1 - 别再让 gitflo...
加权指数 完成W底後,在10/19站上颈线,直接一路狂奔直到11/19,历经1个月的多头格局, 在这...
经过了连续5篇复杂度略高的物理模拟系列,我在想看官们多少会有点疲乏~ 所以我在规划了几篇『中场休息』...