简单理解常用设计模式(四)装饰模式

下面说一个笔者理解了蛮久的模式,笔者基础仅一般,所以理解有些慢。各位如果和笔者相似,请debug代码一步步刨开理解。

现在有这样一个场景,类似qq秀(女生的话理解成暖暖,嘿嘿),用来换装穿衣,文字显示即可,简单代码实现,怎么做呢?

学生党并且基础不好的可能是这样:写一个persion类,属性包括姓名,方法有穿衣服,穿裤子,穿鞋子,方法实现就是打印这几个字,然后show方法用来打印人名,最后在main方法new Persion对象,对象调用穿着方法和show方法即可。

这样编写的代码属于死代码,假如要新增穿帽子方法就得修改源码的类,(三)文章里笔者写了开闭原则,意思是可以扩展但不能修改源码,上述写法就犯了这个错。

普通开发者,没有学习过设计模式的,可能这样写:抽象一个服装类接口,内有show方法,具体修饰类实现接口,最后写一个Perison类用于显示人名。

UML如下:


这样做是符合了开闭原则,但在调用时候每个具体装饰类的对象要各自调用自己的show方法,例如原书案例调用方式如下:


这样做不好,百度有一些理由大家可以搜搜,笔者就认为代码重复不好看,一个作用相同的方法干嘛调用三次呢。

所以下面就是前辈们搞出的装饰模式:动态的给一个对象添加额外的职责(功能,方法)

UML大致如下:


调用类如下:

package com.gcc.decoratorModel;
/**
 * 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为
 */
public class TestDecorator {

	public static void main(String[] args) {
		Persion persion = new Persion("张三");
		Persion cpersion = new DecoratorClothes(persion);
		Persion ppersion = new DecoratorPants(cpersion);
		Persion spersion=new DecoratorShoes(ppersion);
		spersion.show();
	}
	
}

Persion类如下:

package com.gcc.decoratorModel;
/**
 * 定义被装饰者
 */
public class Persion {

	public Persion() {
		super();
	}

	public Persion(String name) {
		System.out.print(name);
	}

	public void show(){};
	
}

装饰类如下:

package com.gcc.decoratorModel;
/**
 *定义装饰者
 */
public class Decorator extends Persion {

	private Persion persion;

	public Decorator() {
		super();
	}

	public Decorator(Persion persion) {
		//super();//可以注解掉,也可以带上,因为再父类的构造方法没有操作,不影响结果
		this.persion = persion;
	}

	@Override
	public void show() {
		persion.show();
	}

	
	
}

具体装饰类如下:

package com.gcc.decoratorModel;

public class DecoratorClothes extends Decorator {

	public DecoratorClothes() {
		super();
	}
	//super()最近的一个父类,super相当于是指向当前对象的父类,super(参数),调用父类中的某一个构造函数。
	public DecoratorClothes(Persion persion) {
		super(persion);
	}
	
	/**
	 * 装饰动作
	 */
	@Override
	public void show() {
		super.show();
		wearClothes();
	}

	private void wearClothes() {
		System.out.print(" "+"穿衣服");
	}
	
}
package com.gcc.decoratorModel;

public class DecoratorPants extends Decorator {

	public DecoratorPants() {
		super();
	}

	public DecoratorPants(Persion persion) {
		super(persion);
	}
	
	@Override
	public void show() {
		super.show();
		wearPants();
	}

	private void wearPants() {
		System.out.print(" "+"穿裤子");
	}
	
}
package com.gcc.decoratorModel;

public class DecoratorShoes extends Decorator {

	public DecoratorShoes() {
		super();
	}

	public DecoratorShoes(Persion persion) {
		super(persion);
	}
	
	@Override
	public void show() {
		super.show();
		wearShoes();
	}

	private void wearShoes() {
		System.out.print(" "+"穿鞋子");
	}
	
}

输出结果如下:

张三 穿衣服 穿裤子 穿鞋子

这里说明下执行过程,原案例是c++的,笔者翻译成了java,笔者习惯是从main方法往上追溯,去理解代码。

首先测试类new了Person对象,debug可以看到代码执行到Person类的构造方法;

然后测试类new了具体的装饰类DecoratorClothes对象并传递Person类型参数,debug看到代码进入DecoratorClothes的构造方法,内部又调用父类构造方法,即Decorator的构造方法,得到的Person对象(注:此对象也可以是Person的子类类型)赋值给类的成员变量,同时提供由成员变量调用的show方法。

接着测试类new了具体的装饰类DecoratorPants对象并传递Person类型参数,此参数是DecoratorClothes对象向上转型到Person得到的,接着步骤和上述一样。

第三次装饰行为和第二次雷同。

最后执行show方法,这时有意思的东西来了,debug执行顺序是:

1:DecoratorShoes的show方法,执行第一行super.show();

2:Decorator的show方法,执行第一行persion.show();

3:DecoratorPants的show方法,执行第一行super.show();

4:Decorator的show方法,执行第一行persion.show();

5:DecoratorClothes的show方法,执行第一行super.show();

6:Decorator的show方法,执行第一行persion.show();

7:DecoratorClothes的wearClothes方法

8:Decorator的show方法,执行最后的"}"

9:DecoratorPants的wearPants方法

10:Decorator的show方法,执行最后的"}"

11:DecoratorShoes的wearShoes方法

12:结束

笔者的基础一般,如果不深究,装饰模式已经说明完毕,通过重写装饰类的show方法,并在方法内执行需要附加的方法,完成动态的装饰效果。

如果深究,笔者有两处不太理解:

一是执行顺序,先new的对象是DecoratorClothes,为什么测试类执行show方法先调用的却是DecoratorShoes的show方法?最后调用顺序却又按照了new对象的顺序又是为什么?笔者粗略猜测是堆栈的原因,但具体要请教各位geek了。

二是测试类的new对象方式像是套用在一起,最后new得到的对象只执行了一次show方法却能分别执行三个具体装饰类的show方法,这是为什么,不太理解原因,是java的哪个特性做到的?多态?和是不是单例有关吗?





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值