JAVA设计模式之装饰模式

前言

假设有一个接口Human,一个接口的实现类Man。人类Human是可以跑步的,但是不能飞。
如果想给人类加上飞翔的翅膀,可以有三种解决方案:

  • 修改实现类Man的方法,但不符合开闭原则
  • 给实现类Man添加一个子类,扩展一个人类可以飞的功能。问题在于,如果又想给人类增加猎豹般奔跑的速度,需要继续扩展一个子类。显然,使用继承的方式去扩展一个类的功能,会增加类的层级,类的臃肿会加大维护的成本。
  • 使用装饰模式扩展一个类的功能。好处在于,如果继承关系是纵向的,那么装饰类则是某个类横向的扩展,并不会影响继承链上的其他类。例如:C extends B , B extends A,如果需要扩展B的功能,可以设计一个B的装饰类,它并不会影响B的子类C。如果采用在B里面增加方法,势必会使B的所有子类结构被改变

一,装饰模式步骤

基本步骤:
定义一个接口Human
定义一个被装饰的类Man
定义一个装饰的抽象类,内部持有被装饰类的引用
定义一个装饰的实现类

类图如下
在这里插入图片描述
1,定义一个接口Human,
抽取一个抽象方法run,人类是可以跑步的。
代码如下:

public interface Human {
	public void run();
}

2,定义一个被装饰的类Man
代码如下:

public class Man implements Human {
	@Override
	public void run() {
		System.out.println("人会跑步");
	}
}

3,定义一个装饰的抽象类
代码如下

public abstract class AbstractDecorator implements Human{
	//持有被装饰类的引用 
	private Human human;
	
	
	public AbstractDecorator(Human human) {
		this.human = human;
	}
	
	//调用被装饰类的方法
	@Override
	public void run() {
		human.run();
	}
}

第3行,模块间的依赖关系,通过成员变量实现,符合迪米特法则。

第6行,模块间的依赖通过抽象Human产生,而不是通过Man,符合依赖倒置原则。

3,定义一个装饰的实现类
代码如下:

public class ManDecorator1 extends AbstractDecorator {
	public ManDecorator1(Human human) {
		//调用父类的构造方法
		super(human);
	}
	
		//装饰类增加的功能
	private void fly() {
		System.out.println("人可以飞");
	}
 
	//增强了功能的run方法
	@Override
	public void run() {
		super.run();
		fly();
	}
}

4 ,客户端代码如下:

public class Client {
	public static void main(String[] args) {
		//创建被装饰的类
		Human human = new Man();
		
		//创建装饰的类,并添加被装饰类的引用
		Human superMan = new ManDecorator(human);
		
		//执行增强后的run方法
		superMan.run();
	}
}

运行结果
在这里插入图片描述

5 ,扩展
如果人类又进步,能够穿越时空,那继续给他装饰
定义一个装饰的实现类
代码如下

public class ManDecrator2 extends AbstractDecorator {
    public ManDecrator2(Human human) {
        super(human);
    }

    @Override
    public void run() {
        super.run();
        fly();
    }
    public void fly(){
        System.out.println("可以穿越时空了");
    }
}

客户端代码

 public static void main(String[] args) {
        Human human=new Man();
        // 初始的人类
        human.run();
        Human manDecorator = new ManDecorator1(new ManDecorator2(human));
        manDecorator.run();
    }

测试结果
在这里插入图片描述
功能随便自己组装只需要继承AbstractDecorator而不用修改其他的代码

二,使用场景,及优缺点

使用场景:

替代继承,扩展一个类的功能
动态的给一个对象添加功能,以及动态的撤销该功能
优点:

  • 动态扩展一个实现类的功能,在不需要添加功能的时候,可以撤销装饰。
  • 装饰类和被装饰类模块间,通过抽象产生依赖,不会相互耦合 装饰模式替换继承,可以避免继承链的子类被影响

缺点
会产生过多的相似的对象,不容易拍错!

三,装饰模式与代理模式的区别

  • 装饰模式:侧重给一个实现类动态添加功能,不会对实现类的方法进行过滤拦截
  • 代理模式:侧重将一个实现类的功能,委托给代理类来处理,可以对实现类的方法进行过滤拦截(某种情况下,可能不执行实现类的方法)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值