├── 观察者模式 ├── tempCodeRunnerFile.ts ├── IObserver.ts ├── village │ ├── Army.ts │ ├── Farmer.ts │ └── Mine.ts ├── README.md ├── Sentry.ts ├── index.ts ├── 鬼子进村.ts └── Event.ts ├── IMG ├── UML.png ├── car.png ├── port.png ├── celuemos.png ├── duckFindC.png ├── duckInterface.png ├── o_Dependency.gif ├── o_aggregation.gif ├── o_composition.gif ├── pointInterface.png ├── o_Generalization.gif └── o_aggregationBase.gif ├── 组合模式-安全 ├── IShape.ts ├── shape │ ├── Rect.ts │ ├── Line.ts │ └── Circle.ts ├── index.ts └── Picture.ts ├── 简单工厂模式 ├── IWeapen.ts ├── weapen │ ├── Gun.ts │ └── Cannon.ts ├── index.ts └── WeapenFactory.ts ├── 工厂模式 ├── README.md ├── weapon │ ├── Weapon.ts │ ├── Gun.ts │ └── MachineGun.ts ├── factory │ ├── WeaponFactory.ts │ ├── GunFactory.ts │ └── MachineGunFactory.ts └── index.ts ├── .gitignore ├── 适配器模式 ├── CN_Socket.ts ├── EN_Socket.ts ├── README.md ├── index.ts └── EN_Adapter.ts ├── 策略模式 ├── attack │ ├── AttackBehavior.ts │ ├── AttackWithFist.ts │ ├── AttackWithSword.ts │ └── AttackWithFalchion.ts ├── index.ts ├── Soldier.ts ├── WeaponFactory.ts └── README.md ├── 外观模式 ├── index.ts ├── application │ ├── Lights.ts │ ├── Popcorn.ts │ └── DVDPlayer.ts ├── HomeThreaterFacade.ts └── README.md ├── 反射 ├── CRect.h ├── CCircle.h ├── Shape.h ├── register.h ├── ClassFactory.h ├── main.cpp ├── ClassFactory.cpp └── README.md ├── 装饰器模式 ├── PRICE.ts ├── Decorator.ts ├── Hamburger.ts ├── index.ts ├── README.md └── material │ ├── Beef.ts │ ├── Chicken.ts │ └── Lettuce.ts ├── 组合模式-透明 ├── shape │ ├── Rect.ts │ ├── Circle.ts │ └── Line.ts ├── IShape.ts ├── index.ts └── Picture.ts ├── 单例模式 ├── 饿汉模式 │ ├── index.ts │ └── Starving.ts └── 懒汉模式 │ ├── index.ts │ └── Slacker.ts ├── 建造者模式 ├── director │ ├── Director.ts │ ├── DirectorCN.ts │ ├── DirectorEU.ts │ └── DirectorUS.ts ├── components │ ├── window │ │ ├── Window.ts │ │ ├── WindowCN.ts │ │ ├── WindowEU.ts │ │ └── WindowUS.ts │ ├── door │ │ ├── Door.ts │ │ ├── DoorCN.ts │ │ ├── DoorEU.ts │ │ └── DoorUS.ts │ └── wall │ │ ├── WallCN.ts │ │ ├── WallEU.ts │ │ ├── WallUS.ts │ │ └── Wall.ts ├── build │ ├── Build.ts │ ├── BuildCN.ts │ ├── BuildEU.ts │ └── BuildUS.ts ├── index.ts ├── House.ts └── README.md ├── .vscode └── launch.json ├── tsconfig.json ├── 重构-影片出租 ├── refactoring │ ├── Price.java │ ├── RegularPrice.java │ ├── ChildPrice.java │ ├── NewReleasePrice.java │ ├── Rental.java │ ├── Test.java │ ├── Movie.java │ └── Customer.java ├── pre │ ├── Rental.java │ ├── Test.java │ ├── Movie.java │ └── Customer.java └── README.md ├── 原型模式 ├── README.md └── index.ts ├── 设计原则.md ├── README.md ├── LICENSE ├── 面试题.md ├── UML.md ├── 环境搭建.md └── 面向对象.md /观察者模式/tempCodeRunnerFile.ts: -------------------------------------------------------------------------------- 1 | farmer -------------------------------------------------------------------------------- /IMG/UML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/UML.png -------------------------------------------------------------------------------- /IMG/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/car.png -------------------------------------------------------------------------------- /IMG/port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/port.png -------------------------------------------------------------------------------- /IMG/celuemos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/celuemos.png -------------------------------------------------------------------------------- /IMG/duckFindC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/duckFindC.png -------------------------------------------------------------------------------- /组合模式-安全/IShape.ts: -------------------------------------------------------------------------------- 1 | interface Shape { 2 | draw(): void 3 | } 4 | 5 | export default Shape -------------------------------------------------------------------------------- /IMG/duckInterface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/duckInterface.png -------------------------------------------------------------------------------- /IMG/o_Dependency.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/o_Dependency.gif -------------------------------------------------------------------------------- /IMG/o_aggregation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/o_aggregation.gif -------------------------------------------------------------------------------- /IMG/o_composition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/o_composition.gif -------------------------------------------------------------------------------- /IMG/pointInterface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/pointInterface.png -------------------------------------------------------------------------------- /简单工厂模式/IWeapen.ts: -------------------------------------------------------------------------------- 1 | abstract class Weapen { 2 | abstract fire() 3 | } 4 | 5 | export default Weapen -------------------------------------------------------------------------------- /IMG/o_Generalization.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/o_Generalization.gif -------------------------------------------------------------------------------- /IMG/o_aggregationBase.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyaocode/DesignPattern/HEAD/IMG/o_aggregationBase.gif -------------------------------------------------------------------------------- /观察者模式/IObserver.ts: -------------------------------------------------------------------------------- 1 | abstract class Observer { 2 | abstract update(): void 3 | } 4 | 5 | export default Observer -------------------------------------------------------------------------------- /工厂模式/README.md: -------------------------------------------------------------------------------- 1 | # 工厂模式 2 | 3 | - 将`new`操作单独封装 4 | 5 | ### 例子 6 | - 买汉堡,直接点餐取餐,不需要亲手自己做 7 | - 商店要做“封装”,要把汉堡做好,直接卖 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | demo/node_modules 2 | node_modules 3 | 4 | *.exe 5 | 6 | *.js.map 7 | 8 | *.d.ts 9 | 10 | *.js -------------------------------------------------------------------------------- /适配器模式/CN_Socket.ts: -------------------------------------------------------------------------------- 1 | class CN_Sokect { 2 | power() { 3 | console.log('中国的插头') 4 | } 5 | } 6 | 7 | export default CN_Sokect -------------------------------------------------------------------------------- /适配器模式/EN_Socket.ts: -------------------------------------------------------------------------------- 1 | abstract class EN_Sokect { 2 | abstract power(enSokect:EN_Sokect): void 3 | } 4 | 5 | export default EN_Sokect 6 | -------------------------------------------------------------------------------- /策略模式/attack/AttackBehavior.ts: -------------------------------------------------------------------------------- 1 | // 攻击方式,用抽象类表示 2 | abstract class AttackBehavior { 3 | abstract attack(name) 4 | } 5 | 6 | export default AttackBehavior -------------------------------------------------------------------------------- /工厂模式/weapon/Weapon.ts: -------------------------------------------------------------------------------- 1 | abstract class Weapon { 2 | name: String 3 | getName(): String { 4 | return this.name 5 | } 6 | } 7 | 8 | export default Weapon 9 | -------------------------------------------------------------------------------- /外观模式/index.ts: -------------------------------------------------------------------------------- 1 | import HomeThreaterFacade from './HomeThreaterFacade' 2 | 3 | const homeThreater = new HomeThreaterFacade(); 4 | 5 | homeThreater.ready() 6 | homeThreater.end() 7 | -------------------------------------------------------------------------------- /简单工厂模式/weapen/Gun.ts: -------------------------------------------------------------------------------- 1 | import Weapen from '../IWeapen' 2 | 3 | class Gun extends Weapen { 4 | fire () { 5 | console.log('use gun') 6 | } 7 | } 8 | 9 | export default Gun -------------------------------------------------------------------------------- /反射/CRect.h: -------------------------------------------------------------------------------- 1 | #include "Shape.h" 2 | 3 | class CRect : public Shape { 4 | public: 5 | void draw() { 6 | cout << "draw a rect" << endl; 7 | } 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /反射/CCircle.h: -------------------------------------------------------------------------------- 1 | #include "Shape.h" 2 | 3 | class CCircle: public Shape { 4 | public: 5 | void draw() { 6 | cout << "draw a circle" << endl; 7 | } 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /简单工厂模式/weapen/Cannon.ts: -------------------------------------------------------------------------------- 1 | import IWeapen from '../IWeapen' 2 | 3 | class Cannon extends IWeapen { 4 | fire () { 5 | console.log('use Cannon') 6 | } 7 | } 8 | 9 | export default Cannon -------------------------------------------------------------------------------- /装饰器模式/PRICE.ts: -------------------------------------------------------------------------------- 1 | //定义各原料的价格 2 | export const BREAD_PRICE: number = 3 3 | export const BEEF_PRICE: number = 10 4 | export const CHIKEN_PRICE: number = 8 5 | export const LETTUCE_PRICE: number = 8 -------------------------------------------------------------------------------- /组合模式-透明/shape/Rect.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Rect extends IShape { 4 | public draw(): void { 5 | console.log(' draw rect') 6 | } 7 | } 8 | 9 | export default Rect -------------------------------------------------------------------------------- /组合模式-安全/shape/Rect.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Rect implements IShape { 4 | public draw(): void { 5 | console.log(' draw rect') 6 | } 7 | } 8 | 9 | export default Rect -------------------------------------------------------------------------------- /工厂模式/weapon/Gun.ts: -------------------------------------------------------------------------------- 1 | import Weapon from './Weapon' 2 | 3 | class Gun extends Weapon { 4 | constructor() { 5 | super() 6 | this.name = 'gun' 7 | } 8 | } 9 | 10 | export default Gun 11 | -------------------------------------------------------------------------------- /适配器模式/README.md: -------------------------------------------------------------------------------- 1 | # 适配器模式 2 | 3 | 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 4 | 5 | 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。 -------------------------------------------------------------------------------- /适配器模式/index.ts: -------------------------------------------------------------------------------- 1 | import CN_Socket from './CN_Socket'; 2 | import EN_Adapter from './EN_Adapter'; 3 | 4 | const cnSocket = new CN_Socket(); 5 | const enSokect = new EN_Adapter(cnSocket); 6 | 7 | enSokect.power(); -------------------------------------------------------------------------------- /反射/Shape.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Shape 8 | { 9 | public: 10 | virtual void draw() = 0; 11 | }; 12 | -------------------------------------------------------------------------------- /策略模式/index.ts: -------------------------------------------------------------------------------- 1 | import Soldier from './Soldier' 2 | 3 | const erye: Soldier = new Soldier('关二爷') 4 | 5 | erye.performAttack(); 6 | 7 | // 关二爷切换装备 8 | erye.setWeapon(1); 9 | erye.performAttack(); 10 | -------------------------------------------------------------------------------- /组合模式-安全/shape/Line.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Line implements IShape { 4 | public draw(): void { 5 | console.log(' draw line ') 6 | } 7 | } 8 | 9 | export default Line 10 | -------------------------------------------------------------------------------- /组合模式-透明/shape/Circle.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Circle extends IShape { 4 | public draw():void { 5 | console.log(" draw circle "); 6 | }; 7 | } 8 | 9 | export default Circle -------------------------------------------------------------------------------- /组合模式-透明/shape/Line.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Line extends IShape { 4 | public draw(): void { 5 | console.log(' draw line ') 6 | } 7 | } 8 | 9 | export default Line 10 | -------------------------------------------------------------------------------- /单例模式/饿汉模式/index.ts: -------------------------------------------------------------------------------- 1 | import Singleton from './Starving' 2 | 3 | const obj_1: Singleton = Singleton.getInstance() 4 | const obj_2: Singleton = Singleton.getInstance() 5 | 6 | // 判断是否为同一对象 7 | console.log(obj_1 === obj_2) -------------------------------------------------------------------------------- /组合模式-安全/shape/Circle.ts: -------------------------------------------------------------------------------- 1 | import IShape from "../IShape"; 2 | 3 | class Circle implements IShape { 4 | public draw():void { 5 | console.log(" draw circle "); 6 | }; 7 | } 8 | 9 | export default Circle -------------------------------------------------------------------------------- /建造者模式/director/Director.ts: -------------------------------------------------------------------------------- 1 | import House from '../House' 2 | import Build from '../build/Build'; 3 | 4 | abstract class Director { 5 | protected build: Build 6 | abstract construct(): House 7 | } 8 | 9 | export default Director -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "type": "java", 5 | "name": "CodeLens (Launch) - MainTest", 6 | "request": "launch", 7 | "mainClass": "MainTest" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /单例模式/懒汉模式/index.ts: -------------------------------------------------------------------------------- 1 | import Singleton from './Slacker' 2 | 3 | const obj_1: Singleton = new Singleton().getInstance() 4 | const obj_2: Singleton = new Singleton().getInstance() 5 | 6 | // 判断是否为同一对象 7 | console.log(obj_1 === obj_2) 8 | -------------------------------------------------------------------------------- /工厂模式/weapon/MachineGun.ts: -------------------------------------------------------------------------------- 1 | import Weapon from './Weapon' 2 | 3 | class MachineGun extends Weapon { 4 | constructor() { 5 | super() 6 | this.name = 'machine gun' 7 | } 8 | } 9 | 10 | export default MachineGun 11 | -------------------------------------------------------------------------------- /观察者模式/village/Army.ts: -------------------------------------------------------------------------------- 1 | import Observer from '../IObserver'; 2 | 3 | class Army extends Observer { 4 | update(): void { 5 | this.fight(); 6 | } 7 | fight() { 8 | console.log('准备战斗') 9 | } 10 | } 11 | 12 | export default Army -------------------------------------------------------------------------------- /观察者模式/village/Farmer.ts: -------------------------------------------------------------------------------- 1 | import Observer from '../IObserver'; 2 | 3 | class Farmer extends Observer { 4 | update() { 5 | this.escape(); 6 | } 7 | escape() { 8 | console.log('逃跑') 9 | } 10 | } 11 | 12 | export default Farmer -------------------------------------------------------------------------------- /观察者模式/village/Mine.ts: -------------------------------------------------------------------------------- 1 | import Observer from '../IObserver'; 2 | 3 | class Mine extends Observer { 4 | update(): void { 5 | this.ready(); 6 | } 7 | ready() { 8 | console.log('地雷挂线') 9 | } 10 | } 11 | 12 | export default Mine -------------------------------------------------------------------------------- /建造者模式/components/window/Window.ts: -------------------------------------------------------------------------------- 1 | class Windows { 2 | protected style: String 3 | 4 | public getStyle(): String { 5 | return this.style 6 | } 7 | public setStyle(style: String): void { 8 | this.style = style 9 | } 10 | } 11 | 12 | export default Windows -------------------------------------------------------------------------------- /策略模式/attack/AttackWithFist.ts: -------------------------------------------------------------------------------- 1 | import AttackBehavior from "./AttackBehavior"; 2 | 3 | //实现用剑杀敌行为的方法类 4 | class AttackWithFist extends AttackBehavior { 5 | attack(name) { 6 | console.log(name + '用拳头杀敌!') 7 | } 8 | } 9 | 10 | export default AttackWithFist -------------------------------------------------------------------------------- /策略模式/attack/AttackWithSword.ts: -------------------------------------------------------------------------------- 1 | import AttackBehavior from "./AttackBehavior"; 2 | 3 | //实现用剑杀敌行为的方法类 4 | class AttackWithSword extends AttackBehavior { 5 | attack(name) { 6 | console.log(name + '用剑杀敌!') 7 | } 8 | } 9 | 10 | export default AttackWithSword -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es6", 5 | "module":"commonjs", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "typeRoots": [ 8 | "node_modules/@types" 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /策略模式/attack/AttackWithFalchion.ts: -------------------------------------------------------------------------------- 1 | import AttackBehavior from "./AttackBehavior"; 2 | 3 | //实现用剑杀敌行为的方法类 4 | class AttackWithFalchion extends AttackBehavior { 5 | attack(name) { 6 | console.log(name + '用青龙偃月刀杀敌!') 7 | } 8 | } 9 | 10 | export default AttackWithFalchion -------------------------------------------------------------------------------- /装饰器模式/Decorator.ts: -------------------------------------------------------------------------------- 1 | import Hamburger from './Hamburger' 2 | 3 | abstract class Decorator extends Hamburger { 4 | hamburger: Hamburger 5 | 6 | public abstract getDescription(): string 7 | 8 | public abstract cost(): number 9 | } 10 | 11 | export default Decorator 12 | -------------------------------------------------------------------------------- /单例模式/饿汉模式/Starving.ts: -------------------------------------------------------------------------------- 1 | class Singleton { 2 | private static instance: Singleton = new Singleton() 3 | constructor() { 4 | console.log('懒汉单例') 5 | } 6 | public static getInstance() { 7 | return Singleton.instance 8 | } 9 | } 10 | 11 | export default Singleton 12 | -------------------------------------------------------------------------------- /建造者模式/build/Build.ts: -------------------------------------------------------------------------------- 1 | import House from "../House"; 2 | 3 | abstract class Build { 4 | 5 | public abstract getHourse():House; 6 | 7 | public abstract creatWall(): void; 8 | public abstract creatDoor(): void; 9 | public abstract creatWindow(): void; 10 | 11 | } 12 | 13 | export default Build -------------------------------------------------------------------------------- /建造者模式/components/door/Door.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * door 接口 3 | */ 4 | class Door { 5 | protected style: String 6 | 7 | public getStyle(): String { 8 | return this.style 9 | } 10 | public setStyle(style: String): void { 11 | this.style = style 12 | } 13 | } 14 | 15 | export default Door 16 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/Price.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | /** 3 | * Price 4 | */ 5 | public abstract class Price { 6 | abstract int getPriceCode(); 7 | 8 | abstract double getCharge(int daysRented); 9 | 10 | int getfrequentRenterPoints(int daysRented) { 11 | return 1; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /工厂模式/factory/WeaponFactory.ts: -------------------------------------------------------------------------------- 1 | import Weapon from '../weapon/Weapon' 2 | 3 | abstract class WeaponFactory { 4 | abstract createWeapon(): Weapon 5 | 6 | getWeapon(): Weapon { 7 | const weapon: Weapon = this.createWeapon() 8 | return weapon 9 | } 10 | } 11 | 12 | export default WeaponFactory -------------------------------------------------------------------------------- /工厂模式/factory/GunFactory.ts: -------------------------------------------------------------------------------- 1 | import WeaponFactory from './WeaponFactory' 2 | import Weapon from '../weapon/Weapon' 3 | import Gun from '../weapon/Gun' 4 | 5 | class GunFactory extends WeaponFactory { 6 | createWeapon(): Weapon { 7 | console.log('use gun') 8 | return new Gun() 9 | } 10 | } 11 | 12 | export default GunFactory -------------------------------------------------------------------------------- /装饰器模式/Hamburger.ts: -------------------------------------------------------------------------------- 1 | import { BREAD_PRICE } from "./PRICE"; 2 | 3 | // 汉堡 4 | class Hamburger { 5 | protected description: string = '汉堡组成: bread' 6 | public getDescription(): string { 7 | return this.description 8 | } 9 | public cost(): number { 10 | return BREAD_PRICE 11 | } 12 | } 13 | 14 | export default Hamburger -------------------------------------------------------------------------------- /观察者模式/README.md: -------------------------------------------------------------------------------- 1 | # 发布订阅模式 2 | 3 | ### 作用 4 | - 发布—订阅模式可以广泛应用于异步编程中,这是一种替代传递回调函数的方案。 5 | - 发布—订阅模式可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口。发布—订阅模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响它们之间相互通信。 6 | 7 | ### 实现 8 | - 首先要指定好谁充当发布者(比如售楼处); 9 | - 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者(售楼处的花名册) 10 | - 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函 11 | 12 | -------------------------------------------------------------------------------- /单例模式/懒汉模式/Slacker.ts: -------------------------------------------------------------------------------- 1 | class Singleton { 2 | private static instance: Singleton 3 | constructor() { 4 | console.log('懒汉单例') 5 | } 6 | getInstance() { 7 | if (Singleton.instance === null) { 8 | Singleton.instance = new Singleton() 9 | } 10 | return Singleton.instance 11 | } 12 | } 13 | 14 | export default Singleton 15 | -------------------------------------------------------------------------------- /适配器模式/EN_Adapter.ts: -------------------------------------------------------------------------------- 1 | import EN_Sokect from './EN_Socket' 2 | import CN_Sokect from './CN_Socket' 3 | 4 | class EN_Adapter implements EN_Sokect { 5 | private cnSokect: CN_Sokect 6 | constructor(cnSoket: CN_Sokect) { 7 | this.cnSokect = cnSoket 8 | } 9 | power(): void { 10 | this.cnSokect.power(); 11 | } 12 | } 13 | 14 | export default EN_Adapter -------------------------------------------------------------------------------- /简单工厂模式/index.ts: -------------------------------------------------------------------------------- 1 | import Weapen from './IWeapen' 2 | import WeapenFactory from './WeapenFactory' 3 | 4 | const weapenFactory: WeapenFactory = new WeapenFactory() 5 | 6 | // 获取 Gun 的对象,并调用 7 | const gun: Weapen = weapenFactory.getWeapen('Gun'); 8 | gun.fire() 9 | 10 | // 获取 Cannon 的对象,并调用 11 | const cannon: Weapen = weapenFactory.getWeapen('Cannon'); 12 | cannon.fire() -------------------------------------------------------------------------------- /装饰器模式/index.ts: -------------------------------------------------------------------------------- 1 | import Hamburger from './Hamburger' 2 | import Beef from './material/Beef' 3 | import Lettuce from './material/Lettuce' 4 | 5 | let hamburger: Hamburger = new Hamburger() 6 | 7 | hamburger = new Beef(hamburger) 8 | hamburger = new Lettuce(hamburger) 9 | 10 | console.log('配料:' + hamburger.getDescription()) 11 | console.log('价钱:' + hamburger.cost()) 12 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/RegularPrice.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | public class RegularPrice extends Price{ 4 | 5 | @Override 6 | int getPriceCode() { 7 | return Movie.REGULAR; 8 | } 9 | 10 | public double getCharge(int daysRented) { 11 | double result=2; 12 | if(daysRented>2) 13 | result+=(daysRented-2)*1.5; 14 | return result; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /工厂模式/factory/MachineGunFactory.ts: -------------------------------------------------------------------------------- 1 | import WeaponFactory from './WeaponFactory' 2 | import Weapon from '../weapon/Weapon' 3 | import MachineGun from '../weapon/MachineGun' 4 | 5 | class MachineGunFactory extends WeaponFactory { 6 | createWeapon(): Weapon { 7 | console.log('use machine gun') 8 | return new MachineGun() 9 | } 10 | } 11 | 12 | export default MachineGunFactory -------------------------------------------------------------------------------- /建造者模式/components/door/DoorCN.ts: -------------------------------------------------------------------------------- 1 | import Door from './Door' 2 | 3 | class DoorCN extends Door { 4 | constructor() { 5 | super() 6 | this.style = '中式' 7 | console.log(`${this.style}的门`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default DoorCN 19 | -------------------------------------------------------------------------------- /建造者模式/components/door/DoorEU.ts: -------------------------------------------------------------------------------- 1 | import Door from './Door' 2 | 3 | class DoorEU extends Door { 4 | constructor() { 5 | super() 6 | this.style = '欧式' 7 | console.log(`${this.style}的门`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default DoorEU 19 | -------------------------------------------------------------------------------- /建造者模式/components/door/DoorUS.ts: -------------------------------------------------------------------------------- 1 | import Door from './Door' 2 | 3 | class DoorUN extends Door { 4 | constructor() { 5 | super() 6 | this.style = '美式' 7 | console.log(`${this.style}的门`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default DoorUN 19 | -------------------------------------------------------------------------------- /组合模式-透明/IShape.ts: -------------------------------------------------------------------------------- 1 | abstract class Shape { 2 | abstract draw(): void 3 | add(shape): Shape { 4 | console.log('add shape') 5 | return this 6 | } 7 | remove(shape): Shape { 8 | console.log('remove shape') 9 | return this 10 | } 11 | getChild(shape): Shape { 12 | console.log('remove shape') 13 | return null 14 | } 15 | } 16 | 17 | export default Shape 18 | -------------------------------------------------------------------------------- /建造者模式/components/wall/WallCN.ts: -------------------------------------------------------------------------------- 1 | import Wall from "./Wall"; 2 | 3 | class WallCN extends Wall { 4 | constructor() { 5 | super() 6 | this.style = '中式' 7 | console.log(`${this.style}的墙`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WallCN 19 | -------------------------------------------------------------------------------- /建造者模式/components/wall/WallEU.ts: -------------------------------------------------------------------------------- 1 | import Wall from "./Wall"; 2 | 3 | class WallEU extends Wall { 4 | constructor() { 5 | super() 6 | this.style = '欧式' 7 | console.log(`${this.style}的墙`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WallEU 19 | -------------------------------------------------------------------------------- /建造者模式/components/wall/WallUS.ts: -------------------------------------------------------------------------------- 1 | import Wall from "./Wall"; 2 | 3 | class WallUN extends Wall { 4 | constructor() { 5 | super() 6 | this.style = '美式' 7 | console.log(`${this.style}的墙`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WallUN 19 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/ChildPrice.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | /** 3 | * 儿童电影 4 | */ 5 | public class ChildPrice extends Price{ 6 | 7 | @Override 8 | int getPriceCode() { 9 | return Movie.CHILDRENTS; 10 | } 11 | public double getCharge(int daysRented) { 12 | double result=1.5; 13 | if(daysRented>3) 14 | result+=(daysRented-3)*1.5; 15 | return result; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /装饰器模式/README.md: -------------------------------------------------------------------------------- 1 | # 装饰器模式 2 | 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 3 | 4 | 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 5 | 6 | ### 场景 7 | 汉堡的原料可以为:鸡肉、牛肉、蔬菜等 8 | 9 | 一个汉堡可以为面包片加这些原料的组合: 10 | - 面包+鸡肉 11 | - 面包 + 鸡肉 + 牛肉 12 | - 面包 + 蔬菜 + 牛肉 13 | - 面包 + 鸡肉 + 蔬菜 14 | - 面包 + 鸡肉 + 牛肉 + 蔬菜 15 | - 。。。 16 | 17 | 如果直接使用继承会导致“类爆炸”,即类的数量太多了。 18 | 19 | -------------------------------------------------------------------------------- /建造者模式/components/window/WindowCN.ts: -------------------------------------------------------------------------------- 1 | import Windows from "./Window"; 2 | 3 | class WindowCN extends Windows { 4 | constructor() { 5 | super() 6 | this.style = '中式' 7 | console.log(`${this.style}的窗`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WindowCN 19 | -------------------------------------------------------------------------------- /建造者模式/components/window/WindowEU.ts: -------------------------------------------------------------------------------- 1 | import Windows from "./Window"; 2 | 3 | class WindowEN extends Windows { 4 | constructor() { 5 | super() 6 | this.style = '欧式' 7 | console.log(`${this.style}的窗`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WindowEN 19 | -------------------------------------------------------------------------------- /建造者模式/components/window/WindowUS.ts: -------------------------------------------------------------------------------- 1 | import Windows from "./Window"; 2 | 3 | class WindowUS extends Windows { 4 | constructor() { 5 | super() 6 | this.style = '欧式' 7 | console.log(`${this.style}的窗`) 8 | } 9 | 10 | public getStyle(): String { 11 | return this.style 12 | } 13 | public setStyle(style: String): void { 14 | this.style = style 15 | } 16 | } 17 | 18 | export default WindowUS 19 | -------------------------------------------------------------------------------- /观察者模式/Sentry.ts: -------------------------------------------------------------------------------- 1 | import MyEvent from './Event' 2 | /** 3 | * 哨兵 4 | */ 5 | class Sentry extends MyEvent { 6 | 7 | // 为某个事件添加一个监听对象 8 | addNotice(eventName: string, observer) { 9 | this.listen(eventName, observer) 10 | } 11 | 12 | // 为某个事件移除一个监听对象 13 | removeNotice(eventName: string, observer) { 14 | this.remove(eventName, observer) 15 | } 16 | } 17 | 18 | export default Sentry 19 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/NewReleasePrice.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | public class NewReleasePrice extends Price{ 4 | 5 | @Override 6 | int getPriceCode() { 7 | return Movie.NEW_RELEASE; 8 | } 9 | public double getCharge(int daysRented) { 10 | return daysRented*3; 11 | } 12 | 13 | public int getfrequentRenterPoints(int daysRented) { 14 | return (daysRented > 1 )? 2:1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /建造者模式/index.ts: -------------------------------------------------------------------------------- 1 | import Director from './director/Director' 2 | import DirectorCN from './director/DirectorCN' 3 | import DirectorEU from './director/DirectorEU' 4 | import DirectorUS from './director/DirectorUS' 5 | 6 | let director: Director = null 7 | 8 | director = new DirectorCN() 9 | director.construct() 10 | 11 | director = new DirectorEU() 12 | director.construct() 13 | 14 | director = new DirectorUS() 15 | director.construct() -------------------------------------------------------------------------------- /外观模式/application/Lights.ts: -------------------------------------------------------------------------------- 1 | class Light { 2 | public static instance: Light = null 3 | 4 | public static getInstance(): Light { 5 | if (this.instance == null) { 6 | this.instance = new Light() 7 | } 8 | return this.instance 9 | } 10 | 11 | public on(): void { 12 | console.log('打开电灯') 13 | } 14 | public off(): void { 15 | console.log('关闭电灯') 16 | } 17 | } 18 | 19 | export default Light 20 | -------------------------------------------------------------------------------- /观察者模式/index.ts: -------------------------------------------------------------------------------- 1 | import Sentry from './Sentry'; 2 | import Farmer from './village/Farmer'; 3 | import Mine from './village/Mine'; 4 | import Army from './village/Army'; 5 | 6 | const sentry = new Sentry(); 7 | const farmer = new Farmer(); 8 | const mine = new Mine(); 9 | const army = new Army(); 10 | 11 | sentry.addNotice('鬼子进村', farmer); 12 | sentry.addNotice('鬼子进村', mine); 13 | sentry.addNotice('鬼子进村', army); 14 | 15 | sentry.trigger('鬼子进村') -------------------------------------------------------------------------------- /外观模式/application/Popcorn.ts: -------------------------------------------------------------------------------- 1 | class Popcorn { 2 | public static instance: Popcorn = null 3 | 4 | public static getInstance(): Popcorn { 5 | if (this.instance == null) { 6 | this.instance = new Popcorn() 7 | } 8 | return this.instance 9 | } 10 | 11 | public get(): void { 12 | console.log('拿爆米花') 13 | } 14 | public off(): void { 15 | console.log('把爆米花收起来') 16 | } 17 | } 18 | 19 | export default Popcorn 20 | -------------------------------------------------------------------------------- /外观模式/application/DVDPlayer.ts: -------------------------------------------------------------------------------- 1 | class DVDPlayer { 2 | public static instance: DVDPlayer = null 3 | 4 | public static getInstance(): DVDPlayer { 5 | if (this.instance == null) { 6 | this.instance = new DVDPlayer() 7 | } 8 | return this.instance 9 | } 10 | 11 | public on(): void { 12 | console.log('DVD打开') 13 | } 14 | public off(): void { 15 | console.log('DVD关闭') 16 | } 17 | } 18 | 19 | export default DVDPlayer 20 | -------------------------------------------------------------------------------- /简单工厂模式/WeapenFactory.ts: -------------------------------------------------------------------------------- 1 | import Weapen from './IWeapen' 2 | import Gun from './weapen/Gun' 3 | import Cannon from './weapen/Cannon' 4 | 5 | class WeapenFactory { 6 | getWeapen(w_type: string): Weapen | null { 7 | switch(w_type) { 8 | case 'Gun' : 9 | return new Gun() 10 | case 'Cannon': 11 | return new Cannon() 12 | default: 13 | return null 14 | } 15 | } 16 | } 17 | 18 | export default WeapenFactory 19 | 20 | -------------------------------------------------------------------------------- /反射/register.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 注册映射 3 | */ 4 | 5 | #include "ClassFactory.cpp" 6 | #include "CRect.h" 7 | #include "CCircle.h" 8 | 9 | Shape *CreateCRect() 10 | { 11 | return new CRect(); 12 | } 13 | 14 | Shape *CreateCCircle() 15 | { 16 | return new CCircle(); 17 | } 18 | 19 | void registerClass() 20 | { 21 | ClassFactory *cf = ClassFactory::getInstance(); 22 | cf->registerClass("CRect", CreateCRect); 23 | cf->registerClass("CCircle", CreateCCircle); 24 | } -------------------------------------------------------------------------------- /重构-影片出租/pre/Rental.java: -------------------------------------------------------------------------------- 1 | package movie; 2 | 3 | /** 4 | * 租赁 5 | * 6 | */ 7 | public class Rental { 8 | private Movie _movie; // 影片 9 | private int _daysRented; // 租期 10 | 11 | public Rental(Movie movie, int daysRented) { 12 | _movie = movie; 13 | _daysRented = daysRented; 14 | } 15 | 16 | public int get_daysRented() { 17 | return _daysRented; 18 | } 19 | 20 | public Movie get_movie() { 21 | return _movie; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /装饰器模式/material/Beef.ts: -------------------------------------------------------------------------------- 1 | import Decorator from '../Decorator' 2 | import Hamburger from '../Hamburger' 3 | import { BEEF_PRICE } from '../PRICE'; 4 | 5 | class Beef extends Decorator { 6 | constructor(ham: Hamburger) { 7 | super() 8 | this.hamburger = ham 9 | } 10 | 11 | public getDescription(): string { 12 | return this.hamburger.getDescription() + ', beef' 13 | } 14 | 15 | public cost(): number { 16 | return this.hamburger.cost() + BEEF_PRICE 17 | } 18 | } 19 | 20 | export default Beef -------------------------------------------------------------------------------- /观察者模式/鬼子进村.ts: -------------------------------------------------------------------------------- 1 | import MyEvent from './Event' 2 | 3 | const myEvent = new MyEvent(); 4 | 5 | // 小明订阅消息 6 | myEvent.listen('squareMeter88', function(price, s) { 7 | 8 | console.log('价格= ' + price + ' ' + s) 9 | }) 10 | 11 | 12 | myEvent.listen('squareMeter100', function(price, s) { 13 | // 小红订阅消息 14 | console.log('价格= ' + price + ' ' + s) 15 | }) 16 | 17 | 18 | 19 | myEvent.trigger('squareMeter88', 2000000, 'asdf') // 输出: 2000000 20 | myEvent.trigger('squareMeter100', 3000000, 'asdfasdf') // 输出: 3000000 21 | -------------------------------------------------------------------------------- /反射/ClassFactory.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | typedef function fn_create; 7 | 8 | class ClassFactory 9 | { 10 | private: 11 | map classMap; 12 | static ClassFactory *cf; 13 | public: 14 | // 根据类名得到对应类 15 | void* getClassByName(string name); 16 | 17 | // 注册类的映射 18 | void registerClass(string className, fn_create fn); 19 | 20 | // 单例工厂 21 | static ClassFactory* getInstance(); 22 | 23 | ClassFactory(); 24 | ~ClassFactory(); 25 | }; 26 | -------------------------------------------------------------------------------- /装饰器模式/material/Chicken.ts: -------------------------------------------------------------------------------- 1 | import Decorator from '../Decorator' 2 | import Hamburger from '../Hamburger' 3 | import { CHIKEN_PRICE } from '../PRICE'; 4 | 5 | class Chicken extends Decorator { 6 | constructor(ham: Hamburger) { 7 | super() 8 | this.hamburger = ham 9 | } 10 | 11 | public getDescription(): string { 12 | return this.hamburger.getDescription() + ', chicken' 13 | } 14 | 15 | public cost(): number { 16 | return this.hamburger.cost() + CHIKEN_PRICE 17 | } 18 | } 19 | 20 | export default Chicken -------------------------------------------------------------------------------- /装饰器模式/material/Lettuce.ts: -------------------------------------------------------------------------------- 1 | import Decorator from '../Decorator' 2 | import Hamburger from '../Hamburger' 3 | import { LETTUCE_PRICE } from '../PRICE'; 4 | 5 | class Lettuce extends Decorator { 6 | constructor(ham: Hamburger) { 7 | super() 8 | this.hamburger = ham 9 | } 10 | 11 | public getDescription(): string { 12 | return this.hamburger.getDescription() + ', lettuce' 13 | } 14 | 15 | public cost(): number { 16 | return this.hamburger.cost() + LETTUCE_PRICE 17 | } 18 | } 19 | 20 | export default Lettuce -------------------------------------------------------------------------------- /重构-影片出租/pre/Test.java: -------------------------------------------------------------------------------- 1 | package movie; 2 | 3 | public class Test { 4 | 5 | /** 6 | * @param args 7 | */ 8 | public static void main(String[] args) { 9 | Customer customer = new Customer("ZhangSan"); 10 | 11 | customer.addRental(new Rental(new Movie("aaa", Movie.REGULAR), 1)); 12 | customer.addRental(new Rental(new Movie("bbb", Movie.NEW_RELEASE), 5)); 13 | customer.addRental(new Rental(new Movie("ccc", Movie.CHILDRENS), 1)); 14 | 15 | System.out.println(customer.statement()); 16 | } 17 | } -------------------------------------------------------------------------------- /原型模式/README.md: -------------------------------------------------------------------------------- 1 | ## 使用克隆的原型模式 2 | 3 | 原型模式是用于创建对象的一种模式,如果我们想要创建一个对象, 一种方法是先指定它的类型,然后通过类来创建这个对象。原型模式选择了另外一种方式,我们 不再关心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象。 4 | 5 | 原型模 式的真正目的并非在于需要得到一个一模一样的对象,而是提供了一种便捷的方式去创建某个类 型的对象,克隆只是创建这个对象的过程和手段。 6 | 7 | 原型模式提供了另外一种创建对象的方式,通过克隆对象,我们就不用再关心对象的具体类 型名字。这就像一个仙女要送给三岁小女孩生日礼物,虽然小女孩可能还不知道飞机或者船怎么 说,但她可以指着商店橱柜里的飞机模型说“我要这个”。 8 | 9 | - 基于原型链的委托机制就是原型继承的本质。 10 | - 原型编程中的一个重要特性,即当对象无法响应某个请求时,会把该请求委 托给它自己的原型。 11 | 12 | 原型编程范型至少包括以下基本规则: 13 | - 所有的数据都是对象。 14 | - 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它。 15 | - 对象会记住它的原型。 16 | - 如果对象无法响应某个请求,它会把这个请求委托给它自己的原型。 -------------------------------------------------------------------------------- /工厂模式/index.ts: -------------------------------------------------------------------------------- 1 | import WeaponFactory from './factory/WeaponFactory' 2 | import GunFactory from './factory/GunFactory' 3 | import MachineGunFactory from './factory/MachineGunFactory' 4 | import Weapon from './weapon/Weapon' 5 | 6 | const gunFactory: WeaponFactory = new GunFactory() 7 | const machineGunFactory: WeaponFactory = new MachineGunFactory() 8 | 9 | const gun: Weapon = gunFactory.getWeapon() 10 | console.log('I hava a ' + gun.getName()) 11 | 12 | const machineGun: Weapon = machineGunFactory.getWeapon() 13 | console.log('I have a ' + machineGun.getName()) 14 | -------------------------------------------------------------------------------- /建造者模式/House.ts: -------------------------------------------------------------------------------- 1 | import Door from "./components/door/Door"; 2 | import Wall from "./components/wall/Wall"; 3 | import Windows from "./components/window/Window"; 4 | 5 | class House { 6 | private door: Array = [] 7 | private wall: Array = [] 8 | private windows: Array = [] 9 | 10 | public addDoor(door: Door): void { 11 | this.door.push(door) 12 | } 13 | public addWall(wall: Wall): void { 14 | this.wall.push(wall) 15 | } 16 | public addWindows(windows: Windows): void { 17 | this.windows.push(windows) 18 | } 19 | } 20 | 21 | export default House 22 | -------------------------------------------------------------------------------- /反射/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 1. 编写,调试通过 3 | * 2. 分模块, 函数 4 | * 3. OO设计模式,封装工厂,单利工厂 5 | */ 6 | 7 | #include "Shape.h" 8 | #include "register.h" 9 | 10 | // 做业务逻辑 11 | void drawShape(ClassFactory *cf, string strClassName) { 12 | Shape *s = (Shape *)(cf->getClassByName(strClassName)); 13 | if (s != NULL) 14 | s->draw(); 15 | } 16 | 17 | int main() 18 | { 19 | // 注册映射 20 | registerClass(); 21 | 22 | // 从单例工厂中取出 23 | ClassFactory *cf = ClassFactory::getInstance(); 24 | 25 | // 业务逻辑: 26 | drawShape(cf, "CRect"); 27 | drawShape(cf, "CCircle"); 28 | drawShape(cf, "errorClass"); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/Rental.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | public class Rental { 4 | private Movie movie; 5 | private int daysRented; 6 | 7 | public Rental(Movie movie, int daysRented) { 8 | this.movie = movie; 9 | this.daysRented = daysRented; 10 | } 11 | 12 | public Movie getMovie() { 13 | return movie; 14 | } 15 | 16 | public int getDaysRented() { 17 | return daysRented; 18 | } 19 | 20 | public double getCharge() { 21 | return movie.getCharge(getDaysRented()); 22 | } 23 | 24 | public int getfrequentRenterPoints() { 25 | return movie.getfrequentRenterPoints(getDaysRented()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/Test.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | Customer customer = new Customer("胡耀"); 6 | 7 | Movie movie = new Movie("喜洋洋与灰太狼",Movie.CHILDRENTS); 8 | Rental rental = new Rental(movie, 4); 9 | customer.addRental(rental); 10 | 11 | movie = new Movie("复仇者联盟4",Movie.NEW_RELEASE); 12 | rental = new Rental(movie, 3); 13 | customer.addRental(rental); 14 | 15 | movie = new Movie("肖申克的救赎",Movie.REGULAR); 16 | rental = new Rental(movie, 5); 17 | customer.addRental(rental); 18 | 19 | System.out.println(customer.statement()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /组合模式-安全/index.ts: -------------------------------------------------------------------------------- 1 | import Circle from './shape/Circle' 2 | import Rect from './shape/Rect' 3 | import Line from './shape/Line' 4 | import Picture from './Picture' 5 | 6 | const r1 = new Rect() 7 | const l1 = new Line() 8 | const c1 = new Circle() 9 | const c2 = new Circle() 10 | 11 | const p1 = new Picture('picture1') 12 | p1.add(c1).add(r1) 13 | 14 | const p2 = new Picture('picture2') 15 | p2.add(c1) 16 | .add(l1) 17 | .add(c2) 18 | 19 | const p3 = new Picture('picture3') 20 | p3.add(c1) 21 | .add(r1) 22 | .add(c2) 23 | 24 | const pic = new Picture('组合其他的 pic') 25 | pic 26 | .add(p1) 27 | .add(p2) 28 | .add(p3) 29 | 30 | pic.draw() 31 | -------------------------------------------------------------------------------- /组合模式-透明/index.ts: -------------------------------------------------------------------------------- 1 | import Circle from './shape/Circle' 2 | import Rect from './shape/Rect' 3 | import Line from './shape/Line' 4 | import Picture from './Picture' 5 | 6 | const r1 = new Rect() 7 | const l1 = new Line() 8 | const c1 = new Circle() 9 | const c2 = new Circle() 10 | 11 | const p1 = new Picture('picture1') 12 | p1.add(c1).add(r1) 13 | 14 | const p2 = new Picture('picture2') 15 | p2.add(c1) 16 | .add(l1) 17 | .add(c2) 18 | 19 | const p3 = new Picture('picture3') 20 | p3.add(c1) 21 | .add(r1) 22 | .add(c2) 23 | 24 | const pic = new Picture('组合其他的 pic') 25 | pic 26 | .add(p1) 27 | .add(p2) 28 | .add(p3) 29 | 30 | pic.draw() 31 | -------------------------------------------------------------------------------- /建造者模式/build/BuildCN.ts: -------------------------------------------------------------------------------- 1 | import Build from './Build' 2 | import House from '../House' 3 | import WallCN from '../components/wall/WallCN' 4 | import WindowCN from '../components/window/WindowCN' 5 | import DoorCN from '../components/door/DoorCN' 6 | 7 | class BuildCN extends Build { 8 | private house: House = new House() 9 | 10 | public getHourse(): House { 11 | return this.house 12 | } 13 | 14 | public creatWall(): void { 15 | this.house.addWall(new WallCN()) 16 | } 17 | public creatWindow(): void { 18 | this.house.addWindows(new WindowCN()) 19 | } 20 | public creatDoor(): void { 21 | this.house.addDoor(new DoorCN()) 22 | } 23 | } 24 | 25 | export default BuildCN -------------------------------------------------------------------------------- /建造者模式/build/BuildEU.ts: -------------------------------------------------------------------------------- 1 | import Build from './Build' 2 | import House from '../House' 3 | import WallEU from '../components/wall/WallEU' 4 | import WindowEU from '../components/window/WindowEU' 5 | import DoorEU from '../components/door/DoorEU' 6 | 7 | class BuildEU extends Build { 8 | private house: House = new House() 9 | 10 | public getHourse(): House { 11 | return this.house 12 | } 13 | 14 | public creatWall(): void { 15 | this.house.addWall(new WallEU()) 16 | } 17 | public creatWindow(): void { 18 | this.house.addWindows(new WindowEU()) 19 | } 20 | public creatDoor(): void { 21 | this.house.addDoor(new DoorEU()) 22 | } 23 | } 24 | 25 | export default BuildEU -------------------------------------------------------------------------------- /建造者模式/build/BuildUS.ts: -------------------------------------------------------------------------------- 1 | import Build from './Build' 2 | import House from '../House' 3 | import WallUS from '../components/wall/WallUS' 4 | import WindowUS from '../components/window/WindowUS' 5 | import DoorUS from '../components/door/DoorUS' 6 | 7 | class BuildUS extends Build { 8 | private house: House = new House() 9 | 10 | public getHourse(): House { 11 | return this.house 12 | } 13 | 14 | public creatWall(): void { 15 | this.house.addWall(new WallUS()) 16 | } 17 | public creatWindow(): void { 18 | this.house.addWindows(new WindowUS()) 19 | } 20 | public creatDoor(): void { 21 | this.house.addDoor(new DoorUS()) 22 | } 23 | } 24 | 25 | export default BuildUS -------------------------------------------------------------------------------- /建造者模式/director/DirectorCN.ts: -------------------------------------------------------------------------------- 1 | import Director from './Director' 2 | import BuildCN from '../build/BuildCN' 3 | import House from '../House' 4 | 5 | class DirectorCN extends Director { 6 | windowNum: number = 2 7 | wallNum: number = 4 8 | 9 | constructor() { 10 | super() 11 | this.build = new BuildCN() 12 | } 13 | 14 | public construct(): House { 15 | console.log('建造中式房子') 16 | 17 | this.build.creatDoor() 18 | for (let i = 0; i < this.windowNum; i++) { 19 | this.build.creatWindow() 20 | } 21 | for (let i = 0; i < this.wallNum; i++) { 22 | this.build.creatWall() 23 | } 24 | 25 | return this.build.getHourse() 26 | } 27 | } 28 | 29 | export default DirectorCN -------------------------------------------------------------------------------- /建造者模式/director/DirectorEU.ts: -------------------------------------------------------------------------------- 1 | import Director from './Director' 2 | import BuildEU from '../build/BuildEU' 3 | import House from '../House' 4 | 5 | class DirectorEU extends Director { 6 | windowNum: number = 2 7 | wallNum: number = 4 8 | 9 | constructor() { 10 | super() 11 | this.build = new BuildEU() 12 | } 13 | 14 | public construct(): House { 15 | console.log('建造欧式房子') 16 | 17 | this.build.creatDoor() 18 | for (let i = 0; i < this.windowNum; i++) { 19 | this.build.creatWindow() 20 | } 21 | for (let i = 0; i < this.wallNum; i++) { 22 | this.build.creatWall() 23 | } 24 | 25 | return this.build.getHourse() 26 | } 27 | } 28 | 29 | export default DirectorEU -------------------------------------------------------------------------------- /建造者模式/director/DirectorUS.ts: -------------------------------------------------------------------------------- 1 | import Director from './Director' 2 | import BuildUS from '../build/BuildUS' 3 | import House from '../House' 4 | 5 | class DirectorUS extends Director { 6 | windowNum: number = 2 7 | wallNum: number = 4 8 | 9 | constructor() { 10 | super() 11 | this.build = new BuildUS() 12 | } 13 | 14 | public construct(): House { 15 | console.log('建造欧式房子') 16 | 17 | this.build.creatDoor() 18 | for (let i = 0; i < this.windowNum; i++) { 19 | this.build.creatWindow() 20 | } 21 | for (let i = 0; i < this.wallNum; i++) { 22 | this.build.creatWall() 23 | } 24 | 25 | return this.build.getHourse() 26 | } 27 | } 28 | 29 | export default DirectorUS -------------------------------------------------------------------------------- /建造者模式/components/wall/Wall.ts: -------------------------------------------------------------------------------- 1 | class Wall { 2 | protected height: number 3 | protected width: number 4 | protected style: String 5 | 6 | constructor() { 7 | this.height = 3.5 8 | this.width = 10.5 9 | this.style = '普通' 10 | } 11 | 12 | public getHeight() { 13 | return this.height 14 | } 15 | public setHeight(height): void { 16 | this.height = height 17 | } 18 | 19 | public getWidth(): number { 20 | return this.width 21 | } 22 | public setWidth(width): void { 23 | this.width = width 24 | } 25 | 26 | public getStyle(): String { 27 | return this.style 28 | } 29 | public setStyle(style: String): void { 30 | this.style = style 31 | } 32 | } 33 | 34 | export default Wall -------------------------------------------------------------------------------- /重构-影片出租/pre/Movie.java: -------------------------------------------------------------------------------- 1 | package movie; 2 | 3 | /** 4 | * 影片 5 | */ 6 | public class Movie { 7 | public static final int REGULAR = 0; // 普通片 8 | public static final int NEW_RELEASE = 1; // 新片 9 | public static final int CHILDRENS = 2; // 儿童片 10 | 11 | private String _title; // 名称 12 | private int _priceCode; //类型代号 13 | 14 | public Movie(String title, int priceCode) { 15 | _title = title; 16 | _priceCode = priceCode; 17 | } 18 | 19 | public int get_priceCode() { 20 | return _priceCode; 21 | } 22 | 23 | public void set_priceCode(int code) { 24 | _priceCode = code; 25 | } 26 | 27 | public String get_title() { 28 | return _title; 29 | } 30 | } -------------------------------------------------------------------------------- /策略模式/Soldier.ts: -------------------------------------------------------------------------------- 1 | import AttackBehavior from './attack/AttackBehavior' 2 | import WeaponFactory from './WeaponFactory' 3 | 4 | /** 5 | * 战士类 6 | */ 7 | class Soldier { 8 | name: string 9 | private attackBehavior: AttackBehavior //武器抽象类型指针 10 | 11 | constructor(name = '士兵') { 12 | this.name = name 13 | this.attackBehavior = WeaponFactory.createWeapon() //开局默认创建武器 14 | } 15 | 16 | // 使用武器 17 | performAttack(): void { 18 | this.attackBehavior.attack(this.name) 19 | } 20 | // 切换武器 21 | setWeapon(type: number): void { 22 | this.attackBehavior = WeaponFactory.createWeapon(type) 23 | } 24 | // 其他函数 25 | riding(): void { 26 | console.log('骑马。骑马的汉子威武雄壮~') 27 | } 28 | } 29 | 30 | export default Soldier -------------------------------------------------------------------------------- /原型模式/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 继承 3 | * @param Parent 4 | * @param Child 5 | */ 6 | function extendsClass(Parent, Child) { 7 | function F() {} 8 | F.prototype = Parent.prototype 9 | Child.prototype = new F() 10 | Child.prototype.constrctor = Child 11 | return Child 12 | } 13 | 14 | function Animal(name) { 15 | this.name = name 16 | } 17 | Animal.prototype.getName = function() { 18 | return this.name 19 | } 20 | Animal.prototype.live = function() { 21 | console.log('live: 出生到死亡') 22 | } 23 | 24 | function Dog(name) { 25 | this.name = name 26 | } 27 | Dog.prototype.getName = function() { 28 | return this.name 29 | } 30 | 31 | // 原型式继承 32 | extendsClass(Animal, Dog) 33 | 34 | const dog = new Dog('旺财'); 35 | 36 | dog.live(); 37 | const dogName =dog.getName(); 38 | console.log(dogName) -------------------------------------------------------------------------------- /外观模式/HomeThreaterFacade.ts: -------------------------------------------------------------------------------- 1 | import DVDPlayer from './application/DVDPlayer' 2 | import Light from './application/Lights' 3 | import Popcorn from './application/Popcorn' 4 | 5 | class HomeThreaterFacade { 6 | private dvdPlayer: DVDPlayer 7 | private light: Light 8 | private popcorn: Popcorn 9 | 10 | constructor() { 11 | this.dvdPlayer = new DVDPlayer() 12 | this.light = new Light() 13 | this.popcorn = new Popcorn() 14 | } 15 | 16 | ready(): void { 17 | console.log('开始播放电影!') 18 | this.popcorn.get() 19 | this.light.off() 20 | this.dvdPlayer.on() 21 | } 22 | 23 | end(): void { 24 | console.log('电影播放完了。') 25 | this.light.on() 26 | this.dvdPlayer.off() 27 | this.popcorn.off() 28 | } 29 | } 30 | 31 | export default HomeThreaterFacade 32 | -------------------------------------------------------------------------------- /策略模式/WeaponFactory.ts: -------------------------------------------------------------------------------- 1 | import AttackBehavior from './attack/AttackBehavior' 2 | import AttackWithFalchion from './attack/AttackWithFalchion' 3 | import AttackWithSword from './attack/AttackWithSword' 4 | import AttackWithFist from './attack/AttackWithFist' 5 | 6 | /** 7 | * 武器的简单工厂 8 | */ 9 | class WeaponFactory { 10 | static createWeapon(type = 2): AttackBehavior { 11 | let attackBehavior: AttackBehavior = null 12 | switch (type) { 13 | case 1: 14 | attackBehavior = new AttackWithFalchion() 15 | break 16 | case 2: 17 | attackBehavior = new AttackWithSword() 18 | break 19 | default: 20 | attackBehavior = new AttackWithFist() 21 | break 22 | } 23 | return attackBehavior 24 | } 25 | } 26 | 27 | export default WeaponFactory -------------------------------------------------------------------------------- /建造者模式/README.md: -------------------------------------------------------------------------------- 1 | # 建造者模式 2 | 3 | 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 4 | 5 | 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 6 | 7 | ### 意图 8 | 9 | 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 10 | 11 | ### 主要解决 12 | 13 | 主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。 14 | 15 | ### 何时使用 16 | 17 | 一些基本部件不会变,而其组合经常变化的时候。 18 | 19 | ### 如何解决 20 | 21 | 将变与不变分离开。 22 | 23 | ### 关键代码 24 | 25 | - 建造者 26 | - 创建和提供实例 27 | - 导演 28 | - 管理建造出来的实例的依赖关系 29 | 30 | ### 优点 31 | 32 | 1. 建造者独立,易扩展。 33 | 2. 便于控制细节风险。 34 | 35 | ### 缺点 36 | 37 | 1. 产品必须有共同点,范围有限制。 38 | 2. 如内部变化复杂,会有很多的建造类。 39 | 40 | ### 使用场景 41 | 42 | 1. 需要生成的对象具有复杂的内部结构。 43 | 2. 需要生成的对象内部属性本身相互依赖。 44 | 45 | ## 注意事项 46 | 47 | 与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。 48 | -------------------------------------------------------------------------------- /反射/ClassFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "ClassFactory.h" 2 | 3 | // 单例指针 4 | ClassFactory* ClassFactory::cf = NULL; 5 | 6 | // 获取单例 7 | ClassFactory* ClassFactory::getInstance() { 8 | if (cf == nullptr) { 9 | cf = new ClassFactory; 10 | } 11 | return cf; 12 | } 13 | 14 | // 写入map 15 | void ClassFactory::registerClass(string className, fn_create fn) { 16 | classMap[className] = fn; 17 | } 18 | 19 | // 从map中得到对应类 20 | void* ClassFactory::getClassByName(string name) { 21 | map::const_iterator it = classMap.find(name); 22 | if (it == classMap.end()) { 23 | cout << "没有这个类: " + name << endl; 24 | return NULL; 25 | } 26 | // second为写入map时的value值 27 | fn_create fn = it->second; 28 | 29 | return fn == NULL ? NULL : fn(); 30 | } 31 | 32 | ClassFactory::ClassFactory() {} 33 | 34 | ClassFactory::~ClassFactory() {} -------------------------------------------------------------------------------- /组合模式-安全/Picture.ts: -------------------------------------------------------------------------------- 1 | import Shape from './IShape'; 2 | 3 | class Picture implements Shape { 4 | private picList: Array = [] 5 | private name: String 6 | 7 | constructor(name) { 8 | this.name = name 9 | } 10 | 11 | public add(shape: Shape): Picture { 12 | this.picList.push(shape) 13 | return this 14 | } 15 | 16 | public remove(picture): Picture { 17 | for (let i = 0; i < this.picList.length; i++) { 18 | if (picture === this.picList[i]) { 19 | this.picList.splice(i, 1) 20 | } 21 | } 22 | return this 23 | } 24 | 25 | public getChild(i: number): Shape { 26 | return this.picList[i] 27 | } 28 | 29 | public draw(): void { 30 | console.log(this.name) 31 | this.picList.forEach(picture => { 32 | picture.draw() 33 | }) 34 | } 35 | } 36 | 37 | 38 | export default Picture -------------------------------------------------------------------------------- /外观模式/README.md: -------------------------------------------------------------------------------- 1 | # 外观模式 2 | 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。 3 | 4 | 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。 5 | 6 | ### 意图 7 | 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 8 | 9 | ### 主要解决 10 | 降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。 11 | 12 | ### 何时使用 13 | 1. 客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 14 | 2. 定义系统的入口。 15 | 16 | ### 如何解决 17 | 客户端不与系统耦合,外观类与系统耦合。 18 | 19 | ### 关键代码 20 | 在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。 21 | 22 | ### 应用实例 23 | 1. 去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。 24 | 2. JAVA 的三层开发模式。 25 | 26 | ### 优点 27 | 1. 减少系统相互依赖。 28 | 2. 提高灵活性。 29 | 3. 提高了安全性。 30 | 31 | ### 缺点 32 | 不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。 33 | 34 | ### 使用场景 35 | 1. 为复杂的模块或子系统提供外界访问的模块。 36 | 2. 子系统相对独立。 37 | 3. 预防低水平人员带来的风险。 38 | 39 | ### 注意事项 40 | 在层次化结构中,可以使用外观模式定义系统中每一层的入口。 -------------------------------------------------------------------------------- /组合模式-透明/Picture.ts: -------------------------------------------------------------------------------- 1 | import Shape from './IShape'; 2 | 3 | class Picture extends Shape { 4 | private picList: Array = [] 5 | private name: String 6 | 7 | constructor(name) { 8 | super() 9 | this.name = name 10 | } 11 | 12 | public add(shape: Shape): Shape { 13 | this.picList.push(shape) 14 | return this 15 | } 16 | 17 | public remove(picture): Shape { 18 | for (let i = 0; i < this.picList.length; i++) { 19 | if (picture === this.picList[i]) { 20 | this.picList.splice(i, 1) 21 | } 22 | } 23 | return this 24 | } 25 | 26 | public getChild(i: number): Shape { 27 | return this.picList[i] 28 | } 29 | 30 | public draw(): void { 31 | console.log(this.name) 32 | this.picList.forEach(picture => { 33 | picture.draw() 34 | }) 35 | } 36 | } 37 | 38 | 39 | export default Picture -------------------------------------------------------------------------------- /重构-影片出租/README.md: -------------------------------------------------------------------------------- 1 | # 重构 2 | 这是一个影片出租店用的程序,计算每一位顾客的消费金额并打印报表(statement),操作者告诉程序:顾客租了哪些影片、租期多长,程序便根据租赁时间和影片类型算出费用。 3 | 影片分为三类;普通片、儿童片和新片。除了计算费用, 4 | 还要为常客计算点数; 5 | 点数会随着"租片种类是否为新片"而有不同。 6 | 7 | 8 | ### 代码中存在的缺陷 9 | `Customer`类中的`statement()`较为庞大,做了很多与`Customer`不相干的事情,较为冗杂。 10 | 11 | 12 | 13 | ## 优化 14 | 15 | ### 函数封装 16 | - 将`statement()`函数中计算价格的代码提出 17 | - 代码更为清晰,函数更简短 18 | - 将each改名为`aRental`更加语义化 19 | - 封装后去除冗余的临时变量,使代码逻辑更清晰 20 | - 使用查询函数来做点数计算 21 | - 取代`totalAmount`和`frequentRentalPoints`两个临时变量,使得`statement()`函数更精简,做的事更专一 22 | ### 设计模式应用 23 | - 状态模式(State Pattern) 24 | - 意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。 25 | - 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。 26 | - 何时使用:代码中包含大量与对象状态有关的条件语句。 27 | - 如何解决:将各种具体的状态类抽象出来。 28 | - 29 | ### 类结构调整 30 | - 将积分计算转移到`Rental`中 31 | - 将常客计算逻辑转移到`Rental`中 32 | - 将各类型影片的价格计算调整到`Movie`类中 33 | - 影片类型可能多变,将`Movie`抽出,建立`Movie`子类,不同的影片有不同的计费方法。 34 | -------------------------------------------------------------------------------- /设计原则.md: -------------------------------------------------------------------------------- 1 | # 设计原则 2 | 3 | 设计: 按照哪一种思路或标准来实现功能 4 | 5 | 功能相同,可以有不同的方案来实现。而且伴随着需求的增加,设计的作用才能体现出来。 6 | 7 | 8 | ### SOLID五大设计原则 9 | - `S` 单一职责原则 10 | - 一个程序只做好一件事 11 | - 如果功能过于复杂就拆分开,每隔部分保持独立 12 | - `O` 开放封闭原则 13 | - 对扩展开发,对修改封闭 14 | - 需求增加时,扩展新代码,而不是修改已有代码 15 | - 这是软件设计的终极目标 16 | - `L` 李氏置换原则 17 | - 子类能覆盖父类 18 | - 父类能出现的地方子类就能出现 19 | - `I` 接口独立原则 20 | - 保持接口的单一独立,尽量不要出现“胖接口” 21 | - 就像单一职责原则,但这里更关注接口 22 | - `D` 依赖导致原则 23 | - 面向接口编程,依赖于抽象而不依赖于具体 24 | - 使用方指关注接口而不是具体类的实现 25 | 26 | 27 | 28 | ###《UNIX/LINUX设计哲学》中提到的设计原则 29 | 30 | - 小即是美 31 | - 每部分代码只做好一件事 32 | - 快速建立原型 33 | - 舍弃高效率而取可移植性 34 | - 采用存文本来存储数据 35 | - 充分利用软件的复用 36 | - 使用shell脚本来提高杠杆效应和可移植性 37 | - 避免强制性的用户界面 38 | - 让每个程序都成为过滤器(每个程序都可以是流水线上的一个机器) 39 | 40 | 一些小准则 41 | - 允许用户定制环境 42 | - 尽量使操作系统内核小而轻量化 43 | - 使用小写字母并尽量简短 44 | - 沉默是金(如果一个输入不符规范,就不输出,而不能是返回一个“你怎么怎么错了”的文字) 45 | - 各部分之和大于整体 46 | - 寻求90%人群的解决方案 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 设计模式 2 | 3 | 使用`TypeScript`实现常见的设计模式 4 | 5 | ### 如何运行代码中的`.ts`文件 6 | 使用Node全局安装`typescript`, 在代码目录的终端下运行:`tsc`。将代码编译为es6后使用`node index.js`运行代码。 7 | 8 | 9 | ### [面向对象](面向对象.md) 10 | 11 | ### [UML](UML.md) 12 | 13 | ### [SOLID设计原则](设计原则.md) 14 | 15 | ### 23种设计模式 16 | - 创建型 17 | - 工厂模式 18 | - 工厂方法模式 19 | - 抽象工厂模式 20 | - 创建者模式 21 | - 单例模式 22 | - 原型模式 23 | - 组合型 24 | - 适配器模式 25 | - 装饰器模式 26 | - 代理模式 27 | - 外观模式 28 | - 桥接模式 29 | - 组合模式 30 | - 享元模式 31 | - 行为型 32 | - 策略模式 33 | - 模板方法模式 34 | - 观察者模式 35 | - 迭代器模式 36 | - 职责模式 37 | - 命令模式 38 | - 备忘录模式 39 | - 状态模式 40 | - 访问者模式 41 | - 中介者模式 42 | - 解释器模式 43 | 44 | 45 | 46 | ### ES6继承中的super 47 | 继承类中的构造函数必须调用 super(...),并且在使用 this 之前执行它。 48 | 49 | 但为什么哪? 50 | 51 | 在JavaScript中,继承了其他类的构造函数比较特殊。在继承类中,相应的构造函数被标记为特殊的内部属性 `[[ConstructorKind]]:“derived”`。 52 | 53 | 区别在于: 54 | 55 | - 当一个普通的构造函数运行时,它会创建一个空对象作为 this,然后继续运行。 56 | - 但是当派生的构造函数运行时,与上面说的不同,它指望父构造函数来完成这项工作。 57 | 58 | 所以如果我们正在构造我们自己的构造函数,那么我们必须调用 super,否则具有 this 的对象将不被创建,并报错。 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 胡耀 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/Movie.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | public class Movie { 4 | public static final int CHILDRENTS = 2; 5 | public static final int REGULAR = 0; 6 | public static final int NEW_RELEASE = 1; 7 | 8 | private String title; 9 | 10 | private Price price; 11 | 12 | public Movie(String title, int priceCode) { 13 | this.title = title; 14 | setPriceCode(priceCode); 15 | } 16 | 17 | public String getTitle() { 18 | return title; 19 | } 20 | 21 | public int getPriceCode() { 22 | return price.getPriceCode(); 23 | } 24 | 25 | public void setPriceCode(int arg) { 26 | switch (arg) { 27 | case REGULAR: 28 | price = new RegularPrice(); 29 | break; 30 | case CHILDRENTS: 31 | price = new ChildPrice(); 32 | break; 33 | case NEW_RELEASE: 34 | price = new NewReleasePrice(); 35 | break; 36 | 37 | default: 38 | throw new IllegalArgumentException("Incorrect Price Code"); 39 | } 40 | } 41 | 42 | public double getCharge(int daysRented) { 43 | return price.getCharge(daysRented); 44 | } 45 | 46 | public int getfrequentRenterPoints(int daysRented) { 47 | return price.getfrequentRenterPoints(daysRented); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /面试题.md: -------------------------------------------------------------------------------- 1 | # 场景应用 2 | 3 | ### 打车问题 4 | 5 | - 打车时,可以打专车或快车。任何车都有车牌和名称, 6 | - 不同车价格不同,快车每公里1元,专车每公里2元。 7 | - 行程开始时,显示车辆信息。 8 | - 行程结束时,显示打车金额(假定行程为5公里) 9 | 10 | 题目: 11 | - 画出UML类图 12 | - 用ES6语法写出该实例 13 | 14 | ![car](IMG/car.png) 15 | 16 | ```js 17 | class Car{ 18 | constructor(number, name) { 19 | this.number = number; 20 | this.name = name; 21 | } 22 | } 23 | 24 | class FastCar extends Car { 25 | constructor(number, name) { 26 | super(number, name); 27 | this.price = 1; 28 | } 29 | } 30 | 31 | class SpecialCar extends Car { 32 | constructor(number, name) { 33 | super(number, name); 34 | this.price = 1; 35 | } 36 | } 37 | ``` 38 | 39 | ```js 40 | class Trip { 41 | constructor(car) { 42 | this.car = car; 43 | } 44 | start() { 45 | console.log(`行程开始, 车名:${this.car.name}, 车牌号:${this.car.price * 5}`) 46 | } 47 | end(distance) { 48 | console.log(`行程结束,价格:${this.car.price * distance}`) 49 | } 50 | } 51 | ``` 52 | 53 | ```js 54 | let car = new FastCar(100, '本田'); 55 | let trip = new Trip(car); 56 | 57 | trip.start(); 58 | trip.end(5); 59 | ``` 60 | 61 | 62 | 63 | ### 停车厂问题 64 | - 某停车场,分n层,每层m个车位 65 | - 每隔车位都能监控到车辆的驶入和离开 66 | - 车辆进入前展示每层空余车位数量 67 | - 车辆进入时,摄像头可识别车牌号和时间 68 | - 车辆出来时,出口显示器显示车牌号和停车时间 69 | 70 | 题目: 画出UML类图 71 | 72 | 分析: 73 | - 停车场 74 | - 有n层 75 | - 层 76 | - 车位 77 | - 监控车辆驶入、离开 78 | - 车 79 | - 车牌 80 | 81 | ![停车场](IMG/port.png) -------------------------------------------------------------------------------- /UML.md: -------------------------------------------------------------------------------- 1 | ## UML 2 | Unified Modeing Language 统一建模语言 3 | 4 | ![](IMG/UML.png) 5 | 6 | ### 依赖 & 关联 7 | 方向:我需要XXX,那么我嘚知道XXX,所以指向XXX 8 | - 依赖关系【虚线】较弱的关系,一般用来做传参或返回值 9 | - 关联关系【实线】较强的关系,一般为类中的一个属性 10 | 11 | ### 聚合 & 组合 12 | 方向:菱形就是一个盘子,一个器皿。所以是大的指向少的。 13 | - 聚合【空心菱形】(弱依赖)两者生命周期不一致 14 | - 组合【实心菱形】(强依赖)两者生命周期一致 15 | 16 | ### 继承 & 实现 17 | 方向:子类一定知道父类,所以子指向父 18 | - 继承父类【实线】类和类,继承是很明确的 19 | - 实现接口【虚线】虚即代表接口没有实体 20 | 21 | 22 | ### 泛化 / 继承(Generalization) 23 | ![泛化](IMG/o_Generalization.gif) 24 | 25 | 在上图中,空心的三角表示继承关系(类继承),在UML的术语中,这种关系被称为泛化(Generalization)。Person(人)是基类,Teacher(教师)、Student(学生)、Guest(来宾)是子类。 26 | 27 | 若在逻辑上B是A的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。 28 | 29 | 如果A是基类,B是A的派生类,那么B将继承A的数据和函数。 30 | 如果类A和类B毫不相关,不可以为了使B的功能更多些而让B继承A的功能和属性。 31 | 若在逻辑上B是A的“一种”(a kind of ),则允许B继承A的功能和属性。 32 | 33 | 34 | ### 组合 35 | 36 | ![组合](IMG/o_composition.gif) 37 | 38 | **菱形为实心的**,它代表了一种更为坚固的关系——组合(composition)(聚合类型为复合)。组合表示的关系也是has-a,不过在这里,A的生命期受B控制。即A会随着B的创建而创建,随B的消亡而消亡。 39 | 40 | ![组合](IMG/o_aggregationBase.gif) 41 | 42 | 例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head应该由类Eye、Nose、Mouth、Ear组合而成,不是派生(继承)而成。 43 | 44 | 45 | ### 聚合 46 | 47 | ![聚合](IMG/o_composition.gif) 48 | 49 | 上面图中,有一个**菱形(空心)**表示聚合(aggregation)(聚合类型为共享),聚合的意义表示has-a关系。聚合是一种相对松散的关系,聚合类B不需要对被聚合的类A负责。 50 | 51 | 相当于一个团伙,几个人合在一起可以做成一件事,这件事做完后大家分散开来各自都还存在,各自再做各自的事,他们的生命周期不相关。 52 | 53 | 54 | ### 依赖 55 | ![依赖](IMG/o_Dependency.gif) 56 | 57 | 这里B与A的关系只是一种依赖(Dependency)关系,这种关系表明,如果类A被修改,那么类B会受到影响。 -------------------------------------------------------------------------------- /环境搭建.md: -------------------------------------------------------------------------------- 1 | 1. 第一步创建文件夹 2 | 2. 第二步,`npm init` 3 | 3. 第三步,安装webpack 和对应的工具 4 | ``` 5 | cnpm i webpack webpack-cli --save-dev 6 | cnpm install webpack-dev-server html-webpack-plugin --save-dev 7 | ``` 8 | 9 | 4. 第四步,配置`webpack.dev.config.js` 10 | 11 | 配置webpack,使用html模板和使用devServer来帮我们做静态资源服务器 12 | 13 | ```json 14 | const path = require('path'); 15 | const HtmlWebpackPlugin = require('html-webpack-plugin') 16 | 17 | module.exports = { 18 | entry: './src/index.js', 19 | output: { 20 | path: __dirname, 21 | filename: './release/bundle.js' 22 | }, 23 | plugins: [ 24 | new HtmlWebpackPlugin({ 25 | template: './index.html' 26 | }) 27 | ], 28 | devServer: { 29 | contentBase: path.join(__dirname, './release'), 30 | open: true, 31 | port: 9000 32 | } 33 | } 34 | ``` 35 | 36 | 5. 配置`babel@7`使项目支持ES6 37 | 安装依赖 38 | ``` 39 | npm i babel-core babel-loader@7 babel-preset-env babel-preset-stage-0 -D 40 | ``` 41 | 再配置webpack 42 | ```json 43 | module: { 44 | rules: [ 45 | { 46 | test: /\.js?$/, 47 | loader: 'babel-loader', 48 | exclude: /node_modules/, 49 | options: { 50 | //如果编译的里面有react,那么需要配置presets 51 | presets: [ 52 | 'stage-0', 53 | [ 54 | 'env', 55 | { 56 | targets: { 57 | //表示兼任主流浏览器最新两个版本即可 58 | browsers: ['last 2 versions'] 59 | } 60 | } 61 | ] 62 | ] 63 | } 64 | } 65 | ] 66 | }, 67 | ``` -------------------------------------------------------------------------------- /观察者模式/Event.ts: -------------------------------------------------------------------------------- 1 | import Observer from './IObserver'; 2 | 3 | 4 | class MyEvent { 5 | // 存储事件于其回调函数 6 | static clientList: { 7 | [propName: string]: Array 8 | } = {} 9 | 10 | // 监听事件,为事件名添加回调函数 11 | listen(eventName: string, observer: Observer): void { 12 | if (!MyEvent.clientList[eventName]) { 13 | MyEvent.clientList[eventName] = [] 14 | } 15 | MyEvent.clientList[eventName].push(observer) // 订阅的消息添加进缓存列表 16 | } 17 | 18 | // 出发某事件,调用其所有的回调函数 19 | trigger(eventName, ...args): boolean { 20 | var observers = MyEvent.clientList[eventName] 21 | if (!observers || observers.length === 0) { 22 | // 如果没有绑定对应的消息 23 | return false 24 | } 25 | for (var i = 0, observer; (observer = observers[i++]); ) { 26 | observer.update.apply(observer, args) 27 | } 28 | return true 29 | } 30 | 31 | // 为某个事件移除一个监听对象 32 | remove(eventName: string, observer: Observer): void { 33 | var observers = MyEvent.clientList[eventName] 34 | if (!observers) { 35 | // 如果 eventName 对应的消息没有被人订阅,则直接返回 36 | return 37 | } 38 | if (!observer) { 39 | // 如果没有传入具体的回调函数,表示需要取消 eventName 对应消息的所有订阅 40 | observers && (observers.length = 0) 41 | } else { 42 | for (var l = observers.length - 1; l >= 0; l--) { 43 | // 反向遍历订阅的回调函数列表 44 | var _observer = observers[l] 45 | if (_observer === observer) { 46 | observers.splice(l, 1) // 删除订阅者的回调函数 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | export default MyEvent 54 | -------------------------------------------------------------------------------- /重构-影片出租/refactoring/Customer.java: -------------------------------------------------------------------------------- 1 | package refactoring; 2 | 3 | import java.util.Enumeration; 4 | import java.util.Vector; 5 | 6 | /** 7 | * 消费者 8 | */ 9 | public class Customer { 10 | private String name; 11 | private Vector rentals = new Vector<>(); 12 | 13 | public Customer(String name) { 14 | this.name = name; 15 | } 16 | 17 | public void addRental(Rental arg) { 18 | rentals.addElement(arg); 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | public String statement() { 26 | Enumeration allRental = rentals.elements(); 27 | String result = "Rental Record for " + getName() + "\n"; 28 | while (allRental.hasMoreElements()) { 29 | Rental each = allRental.nextElement(); 30 | result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(each.getCharge()) + "\n"; 31 | } 32 | result += "Amount owed is " + getTotalCharge() + "\n"; 33 | result += "You earned " + getTotalFrequentRenterPoints() + " frequent renter points"; 34 | 35 | return result; 36 | } 37 | // 计算所有费用 38 | private double getTotalCharge() { 39 | double result = 0; 40 | Enumeration allRental = rentals.elements(); 41 | while (allRental.hasMoreElements()) { 42 | Rental each = allRental.nextElement(); 43 | result += each.getCharge(); 44 | } 45 | return result; 46 | } 47 | // 计算常客点数 48 | private double getTotalFrequentRenterPoints() { 49 | int result = 0; 50 | Enumeration allRental = rentals.elements(); 51 | while (allRental.hasMoreElements()) { 52 | Rental each = allRental.nextElement(); 53 | result += each.getfrequentRenterPoints(); 54 | } 55 | return result; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /反射/README.md: -------------------------------------------------------------------------------- 1 | # 反射 2 | 3 | ### 摘要: 4 | 使用C++里的函数指针、map实现了反射机制,能通过输入类名创建对应的类。 5 | 6 | ### 关键字: 7 | 反射机制、单例工厂、函数指针、模块化。 8 | 9 | ### 效果: 10 | 可根据一个字符串形式的类名动态自适应创建对应类,要想添加一个映射关系,就把对应类定义好好到register.h中去添加一个映射即可 11 | 12 | --- 13 | 14 | ### 简单工厂 15 | ShapeFactory 16 | 简单工厂中有很多case 17 | - case 1...n 18 | - new CRect, new CCircle, new Triangle 19 | 20 | 21 | ### factory Pattern 22 | new FactoryRect, new FactoryCircle 23 | 24 | ```cpp 25 | void main() { 26 | // 简单工厂(用switch Case) 27 | ShapeFactory Sh = new ShapeFactory(); 28 | CRect rc = sh->CreateShape(0); 29 | // 抽象工厂 30 | FactoryRect frc = new FacrotyRect(); 31 | CRect = frc->CreateShape(); 32 | 33 | //反射 34 | String ClassName; 35 | cin >> ClassName; // 'Rect' 36 | CShape rc = new ClassName; 37 | // 但上面的输入不能随便输入,用一个配置文件 38 | // *.ini *.json *.xml 39 | ID className 40 | 1 CRect 41 | 2 CCircle 42 | 3 CTriangle 43 | 44 | } 45 | ``` 46 | 47 | 好处: 拓展但不变代码 48 | 49 | ### 目标 50 | 建立下面对应关系: 51 | ``` 52 | "CRect": CreateRect{return new Crect();} 53 | "CCircle": CreateCircle{return new CCircle();} 54 | ``` 55 | 56 | 在C++中使用map 来实现这种映射 57 | ``` 58 | Map m_map; 59 | m_map.inset(k1,v1); 60 | ``` 61 | 62 | 相关知识点: 63 | ```cpp 64 | // 哈希表 map :类名与类创建的映射 65 | // 函数指针 :返回值(函数指针名字*)(参数列表) 66 | 67 | int Add(int a, int b); 68 | 69 | typedef int (fn_ptr_add*)(int, int); 70 | 71 | fn_ptr_add fnAdd = Add; 72 | fnAdd(2, 5); 73 | ``` 74 | 75 | ```cpp 76 | Class CRect { 77 | void draw() { 78 | cout << "this is rect" << endl; 79 | } 80 | } 81 | 82 | Class FactoryRect { 83 | // 编译后 CRect* CreateRect(const FactoryRect* this) 84 | CRect* CreateRect() { 85 | return new CRect(); 86 | } 87 | } 88 | 89 | typedef CRect* (fn_CreateRect*)(void); 90 | 91 | // 绕过方法 92 | CRect* CreateRect() { 93 | return new CRect(); 94 | } 95 | 96 | void main() { 97 | 98 | Map ShapeCreatorMap; 99 | ShapeCreatotMap.insert(pair("CRect", CreateRect)) 100 | 101 | 102 | CRect rc = new CRect(); 103 | rc.draw(); 104 | } 105 | ``` -------------------------------------------------------------------------------- /重构-影片出租/pre/Customer.java: -------------------------------------------------------------------------------- 1 | package movie; 2 | 3 | import java.util.Enumeration; 4 | import java.util.Vector; 5 | 6 | public class Customer { 7 | private String _name;// 姓名 8 | private Vector _rentals = new Vector(); // 租借记录 9 | 10 | public Customer(String name) { 11 | _name = name; 12 | } 13 | 14 | public void addRental(Rental obj) { 15 | _rentals.addElement(obj); 16 | } 17 | 18 | public String get_name() { 19 | return _name; 20 | } 21 | 22 | public String statement() { 23 | double totalAmount = 0; // --总消费金额 24 | int frequentRenterPoints = 0; // --常客积点 25 | Enumeration rentals = _rentals.elements(); 26 | String result = "Rental Record for " + get_name() + "\n"; 27 | 28 | while (rentals.hasMoreElements()) { 29 | double thisAmount = 0; 30 | Rental each = (Rental) rentals.nextElement(); // --取得一笔租借记录 31 | 32 | switch (each.get_movie().get_priceCode()) { // --取得影片出租价格 33 | case Movie.REGULAR: // --普通片 34 | thisAmount += 2; 35 | if (each.get_daysRented() > 2) 36 | thisAmount += (each.get_daysRented() - 2) * 1.5; 37 | break; 38 | case Movie.NEW_RELEASE: // --新片 39 | thisAmount += each.get_daysRented() * 3; 40 | break; 41 | case Movie.CHILDRENS: // --儿童片 42 | thisAmount += 1.5; 43 | if (each.get_daysRented() > 3) 44 | thisAmount += (each.get_daysRented() - 3) * 1.5; 45 | break; 46 | } 47 | 48 | // ---累加常客积点 49 | frequentRenterPoints++; 50 | if (each.get_movie().get_priceCode() == Movie.NEW_RELEASE && each.get_daysRented() > 1) 51 | frequentRenterPoints++; 52 | // ---显示此笔租借数据 53 | result += "\t" + each.get_movie().get_title() + "\t" + String.valueOf(thisAmount) + "\n"; 54 | totalAmount += thisAmount; 55 | } 56 | // ---结尾打印 57 | result += "Amount owed is " + String.valueOf(totalAmount) + "\n"; 58 | result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; 59 | return result; 60 | } 61 | } -------------------------------------------------------------------------------- /面向对象.md: -------------------------------------------------------------------------------- 1 | # 面向对象 2 | 3 | - 函数式(结构化) 4 | - 顺序、判断、循环 5 | - 面向对象(数据结构化) 6 | - 对于计算机,结构化的才是最简单的 7 | - 编程应该: 简单 & 抽象 8 | 9 | ### 类 10 | 类,就是一个模板,可以通过它构造出很多对象。 类里面通常包含一些属性和方法。 11 | 12 | ### 对象 13 | 类的一个实例,一个实体,它拥有类的所有属性和方法,他与其他对象。 14 | 15 | 16 | ## 面向对象三要素 17 | 18 | ### 封装 19 | 封装就是事物抽象为类,把对外接口暴露,将实现和内部数据隐藏,做到权限和保密。 20 | 21 | 从封装实现细节来讲,封装使得对象内部的变化对其他对象而言是透明的,也就是不可见的。 对象对它自己的行为负责。封装使得对象之间的耦合变松散,对象之间只通过暴露接口来通信。 22 | 23 | 24 | ### 继承 25 | 面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 26 | 27 | 通过继承创建的新类称为“子类”或“派生类”。 28 | 被继承的类称为“基类”、“父类”或“超类”。 29 | 继承的过程,就是从一般到特殊的过程。 30 | 要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。 31 | 在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。 32 | 33 | 继承概念的实现方式有三类:实现继承、接口继承和可视继承。 34 | - 实现继承是指使用基类的属性和方法而无需额外编码的能力; 35 | - 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力; 36 | - 可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。 37 | 38 | 39 | 在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。 40 | 41 | 抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class。 42 | 43 | OO开发范式大致为: 44 | ``` 45 | 划分对象 → 抽象类 → 将类组织成为层次化结构(继承和合成) → 用类与实例进行设计和实现几个阶段。 46 | ``` 47 | 48 | ### 多态 49 | 50 | 多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,同一接口不同实现。 51 | 52 | - 多态背后的思想是将“做什么”和“谁去做以及怎样去做”分离开来,也就是将“不变的事 物”与 “可能改变的事物”分离开来。 53 | - 静态类型的面向对象语言通常被设计为可以向上转型:当给一个类变量赋值时,这个变量的类型既可以使用这个类本身,也可以使用这个类的超类。 54 | - 多态的最根本好处在于,你不必再向对象询问“你是什么类型”而后根据得到的答案调用对象的某个行为——你只管调用该行为就是了,其他的一切多态机制都会为你安排妥当。 55 | 56 | 多态例子: 在电影的拍摄现场,当导演喊出“action”时,主角开始背台词,照明师负责打灯 光,后面的群众演员假装中枪倒地,道具师往镜头里撒上雪花。在得到同一个消息时, 每个对象都知道自己应该做什么。如果不利用对象的多态性,而是用面向过程的方式来 编写这一段代码,那么相当于在电影开始拍摄之后,导演每次都要走到每个人的面前, 确认它们的职业分工(类型),然后告诉他们要做什么。如果映射到程序中,那么程序 中将充斥着条件分支语句。 57 | 58 | 实现多态,有二种方式,覆盖,重载。 59 | 60 | - 覆盖,是指子类重新定义父类的虚函数的做法。 61 | - 重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。 62 | 63 | 其实,重载的概念并不属于“面向对象编程”,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。 64 | 65 | 如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。 66 | 67 | 那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是“覆盖”。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚邦定,它就不是多态。” 68 | 69 | 那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。 -------------------------------------------------------------------------------- /策略模式/README.md: -------------------------------------------------------------------------------- 1 | # 策略模式 2 | 3 | 演示代码为关二爷切换武器的场景,下面Readme中讲的是 《HeadFrist中的策略模式》 4 | 5 | **一个问题有多个解决方法**,或者说一个实体有多种表现形式。 6 | 7 | 但是这多个解决方法或表现形式**只需要选择一种就够了**。 8 | 9 | 想要封装这多种解决方法,供选用。 10 | 11 | ### 场景分析 12 | 13 | 鸭子类,假定所有的鸭子都是可以展示(display) 和游泳(swim)的。但可能有橡皮鸭(不会飞)、模型鸭(不会叫)。这个时候如何让飞和叫的这两种行为得到很好的复用哪? 14 | 15 | - 使用继承? 16 | - NO,如果在父类中直接写入飞和叫这两个行为,那么只能给子类提供一种解决方案,做不到对多种行为的封装 17 | - 使用接口? 18 | - 回导致很乱的感觉。 19 | ![接口](../IMG/duckInterface.png) 20 | 21 | 22 | - 第一步,找出变于不变 23 | ![找](../IMG/duckFindC.png) 24 | 25 | - 第二步,针对接口编程,而不是针对实现编程 26 | ![接口编程](../IMG/pointInterface.png) 27 | 28 | 29 | ### UML 30 | ![策略模式](../IMG/celuemos.png) 31 | 32 | 33 | ### 实现代码 34 | 35 | 绿头鸭类 36 | ```java 37 | public class MallardDuck extends Duck { 38 | public MallardDuck() { 39 | quackBehavior = new GaGaQuack(); // quackBehavior是叫声接口类型 40 | flayBehavior = new FlyWithWings(); //flayBehavior是飞行接口类型 41 | } 42 | // 实现接口 43 | public void display() { 44 | System.out.println("看起来头上有点绿"); 45 | } 46 | } 47 | ``` 48 | 49 | 鸭子类 50 | ```java 51 | public abstract class Duck { 52 | 53 | // 为接口类型声明两个引用变量,所有的鸭子子类都继承它们。 54 | FlyBehavior flyBehavior; 55 | QuackBehavior quackBehavior; 56 | 57 | public Fuck{ } 58 | 59 | public void performFly() { 60 | flyBehavior.fly(); // 委托给行为类 61 | } 62 | 63 | public void performQuack() { 64 | quackBehavior.quack(); // 委托给行为类 65 | } 66 | 67 | public void swim() { 68 | System.out.println("所有的鸭子都可以浮起来游泳。"); 69 | } 70 | } 71 | ``` 72 | 73 | FlyBehavior 行为实现类 74 | ```java 75 | // 接口 76 | public interface FlyBehavior { 77 | public void fly(); 78 | } 79 | 80 | // 实现各种行为,这些行为之间是只能选用一个的 81 | public class FlyWithWings implements FlyBehavior { 82 | public void fly() { 83 | System.out.println("我可以用翅膀飞"); 84 | } 85 | } 86 | 87 | public class FlyNoWay implements FlyBehavior { 88 | public void fly() { 89 | System.out.println("我不可以飞"); 90 | } 91 | } 92 | ``` 93 | 94 | QuackBehavior 行为实现类 95 | ```java 96 | public interface QuackBehavior { 97 | public void quack(); 98 | } 99 | 100 | // 实现各种行为,这些行为之间是只能选用一个的 101 | public class GuaGuaQuack implements QuackBehavior { 102 | public void quack() { 103 | System.out.println("我 gua gua 叫"); 104 | } 105 | } 106 | 107 | public class SilenceQuack implements QuackBehavior { 108 | public void quack() { 109 | System.out.println("我沉默"); 110 | } 111 | } 112 | ``` 113 | 114 | 115 | 编译测试类 116 | 117 | ```java 118 | public class MiniDuckSimulator { 119 | public static void main(String[], args) { 120 | Duck mallard = new MallardDuck(); 121 | mallard.performQuack(); 122 | mallard.performFly(); 123 | } 124 | } 125 | ``` 126 | 127 | ### 动态设定行为 128 | 在鸭子类种添加新方法 129 | ```java 130 | public void setFlyBehaver(FlyBehavior fb) { 131 | flyBehavior = fb; 132 | } 133 | public void setQuackBehaver(QuackBehavior qb) { 134 | quackBehavior = qb; 135 | } 136 | ``` --------------------------------------------------------------------------------