设计模式之装饰模式
学习设计模式,最好的学习方式就是去了解该模式要解决的实际问题,只有这样,你才能真正掌握该设计模式的原理。
装饰者模式要解决的问题我的理解是主要解决两个问题:
1.减少类,提升代码的复用性
2.实现开闭原则,对扩展开放,对修改关闭
举一个实际的例子:
针对第一个要解决的问题,举一个例子:店面里面有商品这种抽象类(Shop)该抽象类中有付款方法,店里有四种咖啡,这四种咖啡都继承自抽象类Shop,这样,我们便有四个子类,每一种咖啡有不同的口味,比如加糖,加牛奶加果汁,加水酒。如果要实现这些特殊的特性,采用继承机制,则牛奶需要继承四种咖啡,加糖类咖啡需要继承四种咖啡,......所有的子类都需要继承四种咖啡,这样的结果是,不同口味,不同种类的咖啡的类的数量则是:基类+四种咖啡类*每一种口味的咖啡,总共有这么多的类
几乎是m*n的级别的类数目。这里采用装饰者模式来解决这个问题
商品Shop不变,四种咖啡不变,如Cafe1,Cafe2,Cafe3,Cafe4,这四种咖啡都继承自Shop,这里我们再定义一个装饰类,用于装饰各种开封的口味
如:CafeDeli,该类继承Shop基类,同时申明一个Shop的对象,即:public abstract class CafeDeli implements Shop{
Shop shop;
public CafeDeli(Shop shop){
this.shop=shop;
}
@override
public abstract void cost();
}
//
接下来我们定义
不同口味的装饰方式
public class SugerCafe extends CafeDeli{
Shop shop;
public SugerCafe(Shop shop){
super(shop);
this.shop = shop;
}
public void cost(){
//TODO addsuger
shop.cost();
}
///一次类推定义其他三种口味的咖啡
这样子,我们如果要买哪种类型的咖啡
我们只需要定义声明一种类型的咖啡
然后再申明一种口味的咖啡
这样子就可以实现不同种类的咖啡和不同口味的咖啡
这样子的类个数:基类+四种类型的咖啡+装饰者类+咖啡的口味,类的个数从m*n级别变成了m+n级别
针对第二个要解决的问题举一个例子:
比如我们有一个已经运行了很长时间且非常稳定的方法如付款方法
现在又需求要在方法之前加上付款前校验,在付款后加上付款日志。
这里有两种方法可以解决该问题
第一:在原来的付款方法中加上这两个逻辑,但是这样就破坏了之前稳定的代码,不符合开闭原则,很容易将已经稳定的解决方案破坏掉
第二:采用装饰模式,新声明一个类该类继承自付款抽象类,同时申明一个付款抽象类的对象,如:
public inteface Pay{
public void pay();
}
public class Netpay implements Pay{
public void pay(){
//非常稳定的付款方式,一般是不允许被修改的
}
}
//声明装饰类,解决新需求
public class DologPay implements Pay{
private Pay pay;
public DologPay(Pay pay){
this.pay=pay;
}
public void pay(){
//TODO校验
this.pay();
//TODO 写日志
}
}
采用装饰模式即可实现在不修改类的基础之上,增加其新功能,为后续的扩展做好准备。
//JAVA的IO即采用的这种实现方式,其中的FilterInputStream和FilterOutPutStream扮演了装饰者模式,BufferedInputStream,DataInputStream则成了装饰者的具体实现
而FileInputStream和ByteArrayInputStream则是原始的流类。
}