(四)装饰模式

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

上面引用来自百度百科,装饰模式,通过一个装饰类来包裹真实对象,先关注几个点:

  1. 不改变原类文件
  2. 不使用继承
  3. 动态扩展

下面这张类图也是来自百度百科,我先写装饰模式,后面再扩展一些东西。
Component:待装饰的接口
ConcreteComponent:待装饰的原始类,实现了待装饰接口
Decorator:装饰抽象父类,继承待装饰接口
ConcreteDecorator:装饰子类,实现装饰功能

在这里插入图片描述

最近在看手机,所以我打算用手机这个例子来实现一下装饰模式

//待装饰接口
public interface Phone {
	//买手机方法
	void buy();
}
//待装饰原始类,实现了待装饰接口
public class MiPhone implements Phone {
	@Override
	public void buy() {
		 System.out.println("买了一部小米");
	}
}
//抽象装饰类
public abstract class Decorator implements Phone {
	
	private Phone phone;
	//构造方法,传入待装饰原始类
	public Decorator(Phone phone) {
		this.phone = phone;
	}
	
	@Override
	public void buy() {
		phone.buy();
	}

}
//装饰子类-手机壳(类)
public class KeConcreteDecorator extends Decorator {

	public KeConcreteDecorator(Phone phone) {
		super(phone);
	}
	
	public void buy() {
		super.buy();
		System.out.println("买了一个漂亮的手机壳给手机套上");
	}

}
//装饰子类-手机膜(类)
public class MoConcreteDecorator extends Decorator {
	
	public MoConcreteDecorator(Phone phone) {
		super(phone);
	}

	public void buy() {
		super.buy();
		System.out.println("买了张钢化膜给手机贴上");
	}
}

下面是客户端调用

//客户端
public class DecoratorDemo {

	 public static void main(String[] args) {
		 //创建小米手机实例
		 Phone phone = new MiPhone();
		 //1.只买了手机壳
		 Decorator ke = new KeConcreteDecorator(phone);
		 ke.buy();
		 System.out.println("================================");
		 //2.只买了手机膜
		 Decorator mo = new MoConcreteDecorator(phone);
		 mo.buy();
		 System.out.println("================================");
		 //3.同时买了手机壳和手机膜
		 Decorator mo2 = new MoConcreteDecorator(ke);
		 mo2.buy();
	}
}

这里演示了三种情况
在这里插入图片描述


装饰模式和静态代理模式

初初看装饰模式的时候,瞬间冒出一个想法,这模式跟代理模式很像哦。

  1. 跟原始类解耦
    无论是装饰类或者是代理类,发现都是在不改动原始类的基础上,附加新的功能
  2. 客户端调用方式很像
    在这里插入图片描述
    在这里插入图片描述
    示例中代理类和装饰类的时候,都是传入了那个具体的对象。

下面来解答上面两个问题
是解耦应该没错,在不改动原始类的基础上,实现同一个(待装饰或被代理)接口。但是思想观念上面有一个很大区别。

装饰模式:

  1. 强调的是增强
  2. 客户端主动行为
    客户端主动的行为。像上面的例子,客户端买到了一个小米手机,是一个裸机,打算花点钱买手机壳或手机膜装饰一下手机,可以根据客户端的想法选择装饰。但这是在程序在运行的时候,才增强的功能(装饰)。

静态代理模式:

  1. 强调的是限制
  2. 客户端被动行为

(上图创建userManager的时候,其实是不严谨的,因为我将需要代理的具体对象暴露了出来。创建的具体实例应该在代理类的构造方法中完成)使用静态代理模式模式的时候,客户端是无感的(被动),即客户端并不知道是哪个真实对象(被代理类)。所以在编译阶段,代理类已经指定了使用哪个被代理类(限制)。


现在又回到最上方那句引用有3个关注点
第一点就很清楚了。
第二点,“不使用继承”。

public class KeDemo extends MiPhone {

	public void buy() {
		super.buy();
		System.out.println("买了一个漂亮的手机壳给手机套上");
	}
}

public class MoDemo extends MiPhone{

	public void buy() {
		super.buy();
		System.out.println("买了张钢化膜给手机贴上");
	}
}

public class ClientDemo {

	public static void main(String[] args) {
		MoDemo md = new MoDemo();
		md.buy();
		System.out.println("====================");
		KeDemo kd = new KeDemo();
		kd.buy();
	}
}

在这里插入图片描述
第二点是不能使用这种继承方式,虽然能实现部分的功能,但是就不能达到第三点的要求了,“动态扩展”。这个动态扩展怎么理解?像上面装饰模式的客户端中第三种使用方法,可以将另外一种装饰子类作为构造方法的参数传递(由于他们的顶级父类都是phone),可以同时实现多种装饰,这就是动态扩展了。


装饰模式就介绍到这里了,谢谢大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值