Try   HackMD

Replace Conditional with Polymorphism

練習用的 REPL

function plumages(birds) { return new Map(birds.map(b => [b.name, plumage(b)])); } function speeds(birds) { return new Map(birds.map(b => [b.name, airSpeedVelocity(b)])); } function plumage(bird) { switch (bird.type) { // 一堆 switch,而且在一些地方重複了 case 'EuropeanSwallow': return "average"; case 'AfricanSwallow': return (bird.numberOfCoconuts > 2) ? "tired" : "average"; case 'NorwegianBlueParrot': return (bird.voltage > 100) ? "scorched" : "beautiful"; default: return "unknown"; } } function airSpeedVelocity(bird) { switch (bird.type) { case 'EuropeanSwallow': return 35; case 'AfricanSwallow': return 40 - 2 * bird.numberOfCoconuts; case 'NorwegianBlueParrot': return (bird.isNailed) ? 0 : 10 + bird.voltage / 10; default: return null; } }
function plumages(birds) { return new Map(birds.map(b => [b.name, plumage(b)])); } function speeds(birds) { return new Map(birds.map(b => [b.name, airSpeedVelocity(b)])); } function plumage(bird) { // switch (bird.type) { // case 'EuropeanSwallow': // return "average"; // case 'AfricanSwallow': // return (bird.numberOfCoconuts > 2) ? "tired" : "average"; // case 'NorwegianBlueParrot': // return (bird.voltage > 100) ? "scorched" : "beautiful"; // default: // return "unknown"; // } return new Bird(bird).plumage; // 只是委派行為 } function airSpeedVelocity(bird) { // switch (bird.type) { // case 'EuropeanSwallow': // return 35; // case 'AfricanSwallow': // return 40 - 2 * bird.numberOfCoconuts; // case 'NorwegianBlueParrot': // return (bird.isNailed) ? 0 : 10 + bird.voltage / 10; // default: // return null; // } return new Bird(bird).airSpeedVelocity; // 只是委派行為 } class Bird { // 建立起 parnet class constructor(birdObject) { Object.assign(this, birdObject); } get plumage() { switch (this.type) { case 'EuropeanSwallow': return "average"; case 'AfricanSwallow': return (this.numberOfCoconuts > 2) ? "tired" : "average"; case 'NorwegianBlueParrot': return (this.voltage > 100) ? "scorched" : "beautiful"; default: return "unknown"; } } get airSpeedVelocity() { switch (this.type) { case 'EuropeanSwallow': return 35; case 'AfricanSwallow': return 40 - 2 * this.numberOfCoconuts; case 'NorwegianBlueParrot': return (this.isNailed) ? 0 : 10 + this.voltage / 10; default: return null; } } }
function plumages(birds) { return new Map(birds.map(b => [b.name, plumage(b)])); } function speeds(birds) { return new Map(birds.map(b => [b.name, airSpeedVelocity(b)])); } function plumage(bird) { // return new Bird(bird).plumage; return createBird(bird).plumage; // 改使用 factory } function airSpeedVelocity(bird) { // return new Bird(bird).airSpeedVelocity; return createBird(bird).airSpeedVelocity; // 改使用 factory } class Bird { constructor(birdObject) { Object.assign(this, birdObject); } get plumage() { switch (this.type) { case 'EuropeanSwallow': return "average"; case 'AfricanSwallow': return (this.numberOfCoconuts > 2) ? "tired" : "average"; case 'NorwegianBlueParrot': return (this.voltage > 100) ? "scorched" : "beautiful"; default: return "unknown"; } } get airSpeedVelocity() { switch (this.type) { case 'EuropeanSwallow': return 35; case 'AfricanSwallow': return 40 - 2 * this.numberOfCoconuts; case 'NorwegianBlueParrot': return (this.isNailed) ? 0 : 10 + this.voltage / 10; default: return null; } } } function createBird(bird) { // 將 switch 的部分改成 factory switch (bird.type) { case 'EuropeanSwallow': return new EuropeanSwallow(bird); case 'AfricanSwallow': return new AfricanSwallow(bird); case 'NorweigianBlueParrot': return new NorwegianBlueParrot(bird); default: return new Bird(bird); } } class EuropeanSwallow extends Bird {} // 為每個 switch 做出子類別 class AfricanSwallow extends Bird {} // 為每個 switch 做出子類別 class NorwegianBlueParrot extends Bird {}
function plumages(birds) { return new Map(birds.map(b => [b.name, plumage(b)])); } function speeds(birds) { return new Map(birds.map(b => [b.name, airSpeedVelocity(b)])); } function plumage(bird) { return createBird(bird).plumage; } function airSpeedVelocity(bird) { return createBird(bird).airSpeedVelocity; } class Bird { constructor(birdObject) { Object.assign(this, birdObject); } get plumage() { switch (this.type) { case 'EuropeanSwallow': throw "oops"; // 原本的地方就讓它出錯 case 'AfricanSwallow': return (this.numberOfCoconuts > 2) ? "tired" : "average"; case 'NorwegianBlueParrot': return (this.voltage > 100) ? "scorched" : "beautiful"; default: return "unknown"; } } get airSpeedVelocity() { switch (this.type) { case 'EuropeanSwallow': return 35; case 'AfricanSwallow': return 40 - 2 * this.numberOfCoconuts; case 'NorwegianBlueParrot': return (this.isNailed) ? 0 : 10 + this.voltage / 10; default: return null; } } } function createBird(bird) { switch (bird.type) { case 'EuropeanSwallow': return new EuropeanSwallow(bird); case 'AfricanSwallow': return new AfricanSwallow(bird); case 'NorweigianBlueParrot': return new NorwegianBlueParrot(bird); default: return new Bird(bird); } } class EuropeanSwallow extends Bird { get plumage() { return "average"; // 先把 plumage 的邏輯移到子類別 } } class AfricanSwallow extends Bird {} class NorwegianBlueParrot extends Bird {}
function plumages(birds) { return new Map(birds.map(b => [b.name, plumage(b)])); } function speeds(birds) { return new Map(birds.map(b => [b.name, airSpeedVelocity(b)])); } function plumage(bird) { return createBird(bird).plumage; } function airSpeedVelocity(bird) { return createBird(bird).airSpeedVelocity; } class Bird { constructor(birdObject) { Object.assign(this, birdObject); } get plumage() { return "unknown"; } get airSpeedVelocity() { switch (this.type) { case 'EuropeanSwallow': return 35; case 'AfricanSwallow': return 40 - 2 * this.numberOfCoconuts; case 'NorwegianBlueParrot': return (this.isNailed) ? 0 : 10 + this.voltage / 10; default: return null; } } } function createBird(bird) { switch (bird.type) { case 'EuropeanSwallow': return new EuropeanSwallow(bird); case 'AfricanSwallow': return new AfricanSwallow(bird); case 'NorweigianBlueParrot': return new NorwegianBlueParrot(bird); default: return new Bird(bird); } } class EuropeanSwallow extends Bird { // 抽取邏輯出來 get plumage() { return "average"; } } class AfricanSwallow extends Bird { // 抽取邏輯出來 get plumage() { return (this.numberOfCoconuts > 2) ? "tired" : "average"; } } class NorwegianBlueParrot extends Bird { // 抽取邏輯出來 get plumage() { return (this.voltage > 100) ? "scorched" : "beautiful"; } }
function plumages(birds) { return new Map(birds .map(b => createBird(b)) .map(bird => [bird.name, bird.plumage])); } function speeds(birds) { return new Map(birds .map(b => createBird(b)) .map(bird => [bird.name, bird.airSpeedVelocity])); } function createBird(bird) { switch (bird.type) { case 'EuropeanSwallow': return new EuropeanSwallow(bird); case 'AfricanSwallow': return new AfricanSwallow(bird); case 'NorwegianBlueParrot': return new NorwegianBlueParrot(bird); default: return new Bird(bird); } } class Bird { constructor(birdObject) { Object.assign(this, birdObject); } get plumage() { return "unknown"; } get airSpeedVelocity() { return null; } } class EuropeanSwallow extends Bird { get plumage() { return "average"; } get airSpeedVelocity() { return 35; } } class AfricanSwallow extends Bird { get plumage() { return (this.numberOfCoconuts > 2) ? "tired" : "average"; } get airSpeedVelocity() { return 40 - 2 * this.numberOfCoconuts; } } class NorwegianBlueParrot extends Bird { get plumage() { return (this.voltage > 100) ? "scorched" : "beautiful"; } get airSpeedVelocity() { return (this.isNailed) ? 0 : 10 + this.voltage / 10; } }