php装饰器模式 简书,Decorator模式(装饰器模式)

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

介绍

意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:

1.多层装饰比较复杂。

2.会导致程序中增加很多功能类似的很小的类

使用场景:

1、扩展一个类的功能。

2、动态增加功能,动态撤销。

注意事项:可代替继承。

示例

Display.ts 用于显示字符串的抽象类

export default abstract class Display {

public abstract getColumns(): number;//获取横向字符数

public abstract getRows(): number;//获取纵向行数

public abstract getRowText(row: number): string;//获取第row行的字符串

/**

*显示所有字符

*/

public show(): void {

for (let i = 0; i < this.getRows(); i++) {

console.log(this.getRowText(i));

}

}

}

StringDisplay.ts 用于显示单行字符串的类

import Display from "./Display";

export default class StringDisplay extends Display {

private str: string;//要显示的字符串

constructor(str: string) {

super();

this.str = str;

}

public getColumns(): number {//字符数

return this.str.length;

}

public getRows(): number {//行数1

return 1;

}

public getRowText(row: number): string {//只显示第一行

if (row == 0) {

return this.str;

} else {

return null;

}

}

}

Border.ts 用于显示装饰边框的抽象类

import Display from "./Display";

export default abstract class Border extends Display {

protected display: Display;//装饰物

constructor(display: Display) {

super();

this.display = display;

}

}

SideBorder.ts 用于显示左右边框的类

import Display from "./Display";

import Border from "./Border";

export default class SideBorder extends Border {

private borderChar: string;//装饰边框的字符

constructor(display: Display, ch: string) {//指定Display和装饰边框字符

super(display);

this.borderChar = ch;

}

public getColumns(): number {

return 1 + this.display.getColumns() + 1;//字符数加上两侧边框的字符数

}

public getRows(): number {

return this.display.getRows();

}

public getRowText(row: number) {//字符串加上边框

return this.borderChar + this.display.getRowText(row) + this.borderChar;

}

}

FullBorder.ts 显示上下左右边框

import Display from "./Display";

import Border from "./Border";

export default class FullBorder extends Border {

constructor(display: Display) {

super(display);

}

public getColumns(): number {

return 1 + this.display.getColumns() + 1;//增加左右边框字符数

}

public getRows(): number {

return this.display.getRows() + 2;//增加上下边框字符数

}

public getRowText(row: number) {

if (row == 0 || row == this.display.getRows() + 1) {//上线边框

return `+${this.makeLine('-', this.display.getColumns())}+`;

} else {

return `|${this.display.getRowText(row - 1)}|`;//左右边框

}

}

private makeLine(ch: string, count: number) {

let str = "";

for (let i = 0; i < count; i++) {

str = str + ch;

}

return str;

}

}

index.ts

import Display from "./Display";

import StringDisplay from "./StringDisplay";

import SideBorder from "./SideBorder";

import FullBorder from "./FullBorder";

const b1: Display = new StringDisplay("Hello,World.");//直接显示

const b2: Display = new SideBorder(b1, '#');//增加左右边框'#'

const b3: Display = new FullBorder(b2);//上下左右都加边框

b1.show();

b2.show();

b3.show();

const b4: Display = new SideBorder(//多层边框

new FullBorder(

new FullBorder(

new SideBorder(

new FullBorder(new StringDisplay("Hello,World.")), "*"

)

)

), "/"

)

b4.show();

result

Hello,World. //b1

#Hello,World.# //b2

+--------------+ //b3

|#Hello,World.#|

+--------------+

/+------------------+/ //b4

/|+----------------+|/

/||*+------------+*||/

/||*|Hello,World.|*||/

/||*+------------+*||/

/|+----------------+|/

/+------------------+/

类图

c3b05378308e

类图

角色

Component

增加功能时的核心角色。示例中Display类扮演该角色

ConcreteComponent

该角色实现了Component角色定义的接口。在示例中StringDisplay类扮演该角色

Decorator(装饰物)

该角色具有与Component角色相同的接口,在内部保存了了被装饰的对象->Component。Decorator橘色知道自己要装饰的对象。在示例中,Border类扮演该角色

ConcreteDecorator(具体的装饰物)

该角色是具体的Decorator角色,示例中SideBorder类和FullBorder类扮演该角色

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值