目录
一:装饰模式
1.引出问题
在java中如果存在这样一个类,这个类存在很多属性,并且还可能在运行中添加更多的属性如下:
public class Clothes {
public int buSy; //步上衣
public int nzSy; //牛仔上衣
public int buxy; //步下衣
public int nzxy; //牛仔下衣
public int bukz; //步裤子
public int nzkz; //牛仔裤子
//......n多属性
public int totalPrice; //总价
//TODO:getter();setter()
public Clothes(int buSy, int nzSy, int buxy, int nzxy, int bukz, int nzkz, int totalPrice) {
this.totalPrice = buSy+nzSy+buxy+nzxy+bukz+nzkz;
}
这个类有什么问题呢:如果添加其他衣料,其他类型的衣服类型,那是不是得添加很多属性。这明显有问题,代码太臃肿了。
如果有人将器改造成下面这个样子:
private Map<String, Integer> clothes;
private Integer totalProce;
public Map<String, Integer> getClothes() {
return clothes;
}
public void setClothes(Map<String, Integer> clothes) {
this.clothes = clothes;
}
public Integer getTotalProce() {
return totalProce;
}
public void setTotalProce(Integer totalProce) {
this.totalProce = totalProce;
}
public Clothes() {}
//计算总价
public Clothes(Map<String, Integer> clothes) {
int totalPrice=0;
for(int price:clothes.values()){
totalPrice+=price;
}
this.totalProce=totalPrice;
}
public static void main(String[] args) {
Map<String, Integer> map=new HashMap<>();
map.put("sy", 10);
map.put("xy", 10);
Clothes clothes=new Clothes(map);
System.out.println(clothes.getTotalProce());
}
这样似乎,只要新增一个类型,就往map里添加一个元素。但是有这样一个问题又产生了,先不说其他,总所周知,hashmap本身就不是一个线程安全的,而如果使用hashtable呢,hashtable本身过于沉重。这样改成上述的方式的话,代码臃肿的问题是解决但是又会产生线程安全和效率的问题。
2.解决问题的方案
针对上述问题有没有好的解决方法呢?当然有这里就引用到了设计模式中的装饰模式,这里提供一下基本的解决思路:
3.基本概念
上面说出了基本的概念,我们也来对照官方给出的定义吧。
抽象构件(Component)角色:即将一个复杂类抽象成一个方法的总和,如上面的 抽象类
构建具体化:对抽象构建的实现。
装饰角色:需要进行装饰的角色,其实这里也可以看成上面的抽象类
装饰角色具体化:就是上面的字类的实现。
那么我们就可以将上面的图修改:
废话不多说上代码:
二:代码详解
1.构件或者装饰
public abstract class Clothes {
public abstract Integer totalPrice();
}
2.构建的具体化
//衣服加个具体实现
public class ClothesDecorator extends Clothes{
private Clothes clothes;
public ClothesDecorator(Clothes clothes){
this.clothes=clothes;
}
@Override
public Integer totalPrice() {
return clothes.totalPrice();
}
}
3.装饰具体化一
package test;
//衣服的字类实现之一:牛仔裤子
public class ClothesNZKZ extends Clothes{
@Override
public Integer totalPrice() {
return 10;
}
}
4.装饰具体化二
/衣服的字类实现之一:牛仔上衣
public class ClothesNZSY extends Clothes{
@Override
public Integer totalPrice() {
return 20;
}
}
5.测试
public class test {
public static void main(String[] args) {
ClothesDecorator cd=new ClothesDecorator(new ClothesNZKZ());
System.out.println(cd.totalPrice());
ClothesDecorator cd1=new ClothesDecorator(new ClothesNZSY());
System.out.println(cd1.totalPrice());
}
}
6.说明
具体就不用我说了吧。
三:装饰模式的用途
1.装饰模式的优点
很明显,装饰模式在对于java中的单继承做了很好的扩展,如果以后大家在遇到什么动态扩容的之类的方案不妨考虑一下。
2.装饰模式的缺点
其实就像我们文章一开始所说的一个Map存储完全可以解决这些问题,只是会涉及到线程或者效率问题,但是我们想一下在我们单体垂直应用访问量一般的情况下需要考虑到这个问题么?正如上面代码所揭示的在高并发,低延时,动态扩容的情况下可以有限考虑该模式,否则会造成代码交叉紊乱。
3.应用场景
java中io设计有兴趣的同学可以自行阅读一下源码,这里就不贴出了。