设计模式 - 装饰者模式

先不讲设计模式,先讲一个生活中的例子。山东煎饼(或者肉夹馍)相信大家都吃过,可以自己选择需要的食材,比如,可以加一串里脊,或者培根,多加个蛋,到最后,老板会根据你选择的不同食材给你算价格。其实我们可以拆分开,一个基本面饼+鸡蛋+生菜+里脊+豆奶,这就是一层一层嵌套起来,最后只要输出最终价格。这就是装饰者模式,装饰者模式本质是一种组合的思想(不同于继承的思想),多组合少继承,一层一层添加,共存的意思
装饰者模式:动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。
在这里插入图片描述
Component是定义一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent是定义一个具体的基础对象,就好比肉夹馍的白吉馍,山东煎饼的面饼。可以给这个ConcreteComponent对象添加一些职责,他就是Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对Component来说,是无需知道Decorator的存在,至于ConcreteComponent就是具体的装饰对象,起到了给Component添加职责的功能。
下面用代码举个例子(以山东煎饼为例):

//Component用于计算这个山东煎饼有啥,多少钱
public abstract class Component {
    /**
    * 计算价格,整数不找零
    */
	public abstract Integer calculate();
	/**
    * 煎饼里有啥
    */
	public abstract void show();
}

上面定义一个通用接口用来抽象化增强的行为,下面定义具体的基类,山东煎饼最基础的就是一张面皮,啥都可以不要,你看到面皮,勉强认出他是山东煎饼,所以面皮就是最基础的。

public class ConcreteComponent extends Component {
    /**
    * 计算价格,整数不找零
    */
    @Override
	public Integer calculate(){
	   //面皮2元
	   return 2;
	}
	/**
    * 煎饼里有啥
    */
    @Override
	public void show(){
	    System.out.plantln("面皮");
	}
}

既然基础有了,我的装饰是啥,就是里脊、鸡蛋、生菜这些东西,所以定一个抽象的,大家都按照这个加。

public abstract class Decorator extends Component {
	private Component component;
	
	public Decorator(Component component) {
		this.component = component;
	}
	protected abstract Integer doCalculate();
	protected abstract void doShow();
	/**
    * 计算价格,整数不找零
    */
    @Override
	public Integer calculate(){
	   if(component != null) {
	        return doCalculate() + component.calculate();
		}
	}
	/**
    * 煎饼里有啥
    */
    @Override
	public void show(){
	   if(component != null) {
	        doShow();
	        component.show();
		}
	}
}

下面只要定义好装饰器。

//加鸡蛋
public class ConcreteDecoratorA extends Decorator {
	@Override
	public Integer doCalculate(){
	    //鸡蛋,多加2元
	    return 2;
	}
	@Override
	public void doShow() {
	   System.out.plantln("加一个鸡蛋");
	}
}
 
//加里脊
public class ConcreteDecoratorB extends Decorator {
	@Override
	public Integer doCalculate(){
	    //里脊,多加3元
	    return 3;
	}
	@Override
	public void doShow() {
	   System.out.plantln("加一串里脊");
	}
}

具体的用法:

void main(){
        ConcreteComponent cC = new ConcreteComponent();
		ConcreteDecoratorA cA = new ConcreteDecoratorA(cC);
		ConcreteDecoratorB cB = new ConcreteDecoratorB(cA);
		
		Integer calculate = cB.calculate();
		cB.show();
}

与代理模式的不同
这两个设计模式看起来很像。对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个 接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。
然而,实际上,在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。可以理解成,装饰器模式是代理模式+策略模式(有可能理解的不恰当)。上面的例子是山东煎饼,如果适配一个肉夹馍,他也是可以加生菜和鸡蛋。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值