装饰者模式

借鉴一下大鸟/小菜两个人说的例子,我们来实现一下avatar系统,即换肤系统。

人物出场人手一条内裤,穿什么衣服用户自己搭配。考虑到衣服种类很多,上衣裤子鞋子搭配更多,可能随着系统的迭代,衣服种类会不断增加,基于开放封闭原则,对于易变化的点进行封装,使用扩展的方式来实现穿衣的操作,代码如下(java)

//finery class

public class Finery {

public void Show()

{

System.out.print("Underwear");

}

}

 

//t-shirt finery

public class TShirt extends Finery {

@Override

public void Show()

{

super.Show();

System.out.print(" Tshirt ");

}

}

 

//person class

public class Person {

void ShowFinery(Finery finery)

{

finery.Show();

}

}

 

//client

public class client{

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

Person person = new Person();

Finery finery;

finery = new TShirt();//if you want dress UnderWear and T-shirt

//finery = new Finery();//if you just want to dress Underwear

person.ShowFinery(finery);

}

}

 

这样对于目前的需求来说,已经实现了开放-封闭原则,当你想换一件衣服,不穿T恤了,比如你想穿毛衣了,你可以增加一个 Sweater类,继承自Finery类,在实现展示函数的时候先调用父类(Finery)函数,然后再实现Sweater本身内容。

 

但是这样不是没有问题,按照以上的方式,研发人员可能违背里氏替换原则,也就是说在实现派生类的时候忘记/不想调用父类(Finery)相关函数,导致基础功能(穿内裤)没有实现,后果是你在ShowFinery展示你的服饰的时候,你没有穿内裤,注意哦,T恤和毛衣现在还都是上衣,我们没有穿裤子呢。

 

为了避免只穿上衣的问题,我们现在也实现裤子和鞋子,那么上面的实现实现方式又出现了一个问题,那就是面对多件上衣(m)、多条裤子(n)、多条鞋子(q) 的搭配,你需要实现m*n*q个类去实现所有的服饰展示,类的数量暴增,并且你有没有感觉到这么设计类十分的死板?如果初始的时候人物只实现基础功能(穿一条内裤遮羞),后面附件功能(穿什么上衣、什么裤子、什么鞋子)我们可以动态的增减改多好?装饰者实现的就是此类需求。

 

装饰者模式:动态的为一个对象附加新的职责。

 

特征:

一、动态的,即在程序运行过程中可以为对象附加职责。附加职责的方式有两种:一种是静态继承型,也就是我们经常使用的继承多态,这种方式是在编译的时候指定某个类对于基类增加了什么操作。一种是动态组合型,装饰者模式就是其中一个,这种方式是在软件运行的时候指定某个对象增加操作。

二、附加,即一个类已经实现了基础功能或部分功能,在此基础上动态的为这个类的对象增加新的职责。

 

实现:

Component:定义一个对象接口,可以给这些对象动态地添加职责;

ConcreteComponent:定义一个具体的Component,继承自Component,重写了Component类的虚函数;

Decorator:维持一个指向Component对象的指针,该指针指向需要被装饰的对象;并定义一个与Component接口一致的接口;

ConcreteDecorator:向组件添加职责。

 

我们来看一下上面的例子如何使用装饰者模式实现

 

//just abstract or interface to indicate the func of the component

public abstract class IFinery {

public abstract void Show();

}

 

//the basic func

public class Underwear extends IFinery {

public void Show()

{

System.out.print("Underwear");

}

}

 

// a abstract to decorator the component

public abstract class IFinaryDecorator extends IFinery {

private IFinery m_finery;

public void setFinary(IFinery finery)

{

m_finery = finery;

}

@Override

public void Show()

{

m_finery.Show();

}

}

 

//t-shirt decorator

public class TShirtDecorator extends IFinaryDecorator{

@Override

public void Show()

{

super.Show();

System.out.print("T-Shirt");

}

}

 

//bigtrouser decorator

public class BigTrouserDecorator extends IFinaryDecorator{

public void Show()

{

super.Show();

System.out.print(" BigTrouser");

}

}

 

//client

public class client{

 

/**

* @param args

*/

public static void main(final String[] args) {

// TODO Auto-generated method stub

 

Person person = new Person();

IFinery finery = new Underwear();

person.ShowFinery(finery);//if you just want to dress underwear

IFinaryDecorator TShirtDecorator = new TShirtDecorator();

TShirtDecorator.setFinary(finery);

TShirtDecorator.Show();//if you want dress underwear and T-Shirt

IFinaryDecorator bigtrouserDecorator = new BigTrouserDecorator();

bigtrouserDecorator.setFinary(TShirtDecorator);

bigtrouserDecorator.Show();//if you want dress underwear and T-Shirt and Bigtrouser

}

}

这样可以把服饰类的数量缩减到m+n+q的范围;

 

适用场景:

1. 需要扩展一个类的功能,或给一个类添加附加职责。

2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

 

参考:https://www.cnblogs.com/dongsheng/p/5230854.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值