前言
设计模式遍布我们编码的每一个角落,例如JAVA刚入门那会做的第一个窗口程序用的Swing
中的ActionsListener
类就是观察者模式实现的;以及我们文件操作接触比较多的java.io
包内的类有许多就是装饰者模式设计的。如果深入研究过Spring
源码的人都会有这个感慨:Spring就是一些设计模式狂魔的作品
。
设计模式有一个非常重要的面向对象原则:针对接口编程,不针对实现编程
。
在我们debug排查故障或在写程序的时候多多少少都会有看过Spring MVC
中的一些源码,大多数人都会发现Spring
的代码是比较难看懂的。那是因为我们大多都在用面向实现编程的思维去思考代码。这样去看一群设计模式狂魔整出来的东西当然是有相当大的难度的。我们需要看懂读懂Spring
源码,或者其他开源代码必备的一个良好的功底那就是要熟悉常见的设计模式。
装饰者模式
什么是装饰者模式?我们来看看度娘的解读
动态的将责任附加到对象上。若要扩展功能,装饰者提供了有别于继承的另一种选择
我们先从我们所熟悉的java.io包内的装饰者模式实现的类入手。我们来看一个熟悉的对象集合
BufferedInputStream
跟LinerNumberInputStream
都是扩展自FilterInputStream
,而FilterInputStream
是一个抽象的装饰类。
装饰java.io类
我们从上边的java.io类中分析确认了装饰者的重要用途:动态的将责任附加到对象上。
为什么要使用装饰者模式
我们从设计一个简单饮料店说起,饮料店中有原味奶茶,珍珠奶茶,绿茶,抹茶等;调料有糖,牛奶,奶泡等。我们会在第一时间在脑中进行一次类图分析。
这种设计类似硬编码形式在后期并不能做很好的扩展,并违背了一个非常重要的面向对象设计原则:类应该对扩展开放,对修改关闭
。
我们可以看出这种通过继承设计的饮料店是有很大的缺陷:调料价钱出现改变是会使我们更改现有的代码;一但出现新的调料或开发出新的饮料都需对现有代码作比较大的改动。这样的代码可维护性是非常糟糕的。
接着我们用装饰者模式做一次的重新设计
当我们组件与装饰者模式组合时,就是再加入新的行为。例如红豆+珍珠=红豆珍珠奶茶,新的茶饮出来了,无需在添加一个新的类。
代码实现
饮料抽象类
public abstract class Berverage {//饮料店抽象基类
public String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public abstract int Cost();
}
调料抽象类
public abstract class CondimentDecorator extends Berverage{
public abstract String getDescription();
}
饮料类
public class GreenTea extends Berverage {
public GreenTea () {
description = "this is a cup of green tea ";
}
public int Cost() {
return 5;
}
}
public class MilkTea extends Berverage {
public MilkTea() {
description = "this is a cup of milk tea";
}
public int Cost() {
return 6;
}
}
public class PearlsMilkTea extends Berverage {
public PearlsMilkTea() {
description = "this is a cup of pearls milk tea ";
}
public int Cost() {
return 2;
}
}
调料类
public class Milk extends CondimentDecorator {//牛奶
Berverage berverage;
public Milk( Berverage berverage) {
this.berverage = berverage;
}
public String getDescription() {
return berverage.getDescription()+"+milk";
}
public int Cost() {
return berverage.Cost()+3;
}
}
测试代码
public class Application {
public static void main(String[] args) {
//珍珠奶茶
Berverage berverage1 = new PearlsMilkTea();
System.out.println(berverage1.getDescription() + " cost = " + berverage1.Cost());
//绿茶加牛奶
Berverage berverage = new GreenTea();
berverage = new Milk(berverage);
System.out.println(berverage.getDescription()+"cost = "+berverage.Cost());
}
}
测试结果
点题
装饰者模式:动态的将责任附加到对象上。若要扩展功能,装饰者提供了有别于继承的另一种选择
篇幅中讲到了两个重要的面向对象设计原则
- 针对接口编程,不针对实现编程
- 类应该对扩展开放,对修改关闭
The last
三人行,必有我师。在给大家分享干货的同时,才疏学浅还望大家大刀予以斧正。也欢迎关注我的掘金或简书,名称为柴码
网友评论