装饰模式
说是装饰模式,所以装饰器就需要通过某种方法,与被装饰的对象产生连系
在网上看到有人把装饰模式比作买奶茶
所谓的基类就是绿茶,红茶,奶茶
在这个的基础上,你要添加柠檬,珍珠…就是后来的装饰
我觉得是比较形象的,这里通过几个简单的例子
定义父接口
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:42
*/
public interface ParentInter {
//父接口
// 定义两个抽象方法
void parentA();
void parentB();
}
定义实现父接口的实现类
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:43
*/
public class ParentA implements ParentInter {
private String name = "parentA";
public String getName() {
return name;
}
@Override
public void parentA() {
System.out.println("调用方法A");
}
@Override
public void parentB() {
System.out.println("调用方法B");
}
}
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:43
*/
public class ParentB implements ParentInter{
private String name = "parentB";
@Override
public void parentA() {
System.out.println("调用方法A");
}
@Override
public void parentB() {
System.out.println("调用方法B");
}
public String getName() {
return name;
}
}
然后在定义两个修饰类
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:44
*/
public class DecA implements ParentInter {
ParentA parentInter ;
public DecA(ParentA parentA) {
this.parentInter = parentA;
}
@Override
public void parentA() {
System.out.println("调用方法A");
}
@Override
public void parentB() {
System.out.println("调用方法B");
}
//装饰增强新功能
public void extA(){
System.out.println(parentInter.getName()+"增强方法");
parentA();
}
}
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:46
*/
public class DecB implements ParentInter {
private ParentB parentInter ;
public DecB(ParentB parentB) {
this.parentInter = parentB;
}
@Override
public void parentA() {
System.out.println("调用方法A");
}
@Override
public void parentB() {
System.out.println("调用方法B");
}
//装饰增强新功能
public void extB(){
System.out.println(parentInter.getName()+"增强方法");
parentB();
}
}
这样在就可以通过装饰模式,给我们的基础实现类添加方法,实现增强的效果,也就是加珍珠
package it.luke.decorator.simaple;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/1923:50
*/
public class Maintest {
public static void main(String[] args) {
//普通调用
ParentA parentA = new ParentA();
ParentB parentB = new ParentB();
//没装饰的基类
parentA.parentA();
parentB.parentB();
//对基类进行装饰
DecA decA = new DecA(parentA);
DecB decB = new DecB(parentB);
decA.parentA();
decB.parentB();
decA.extA();
decB.extB();
}
}
/**
调用方法A
调用方法B
调用方法A
调用方法B
parentA增强方法
调用方法A
parentB增强方法
调用方法B
*/
使用装饰模式有一个比较经典的例子就是,java的io流设计
在刚开始接触到java的io流的时候,都会或多或少很乱,虽然主要分成两大类
InputSteam和Outputstream 两大类
但是根据不同的使用环境以及处理模式,最基本的实现类已经不足以处理我们的需求
所以才衍生了那么多
为了记忆,不得已整理了一下
整理了密密麻麻,以为就可以帮助我理解,但是效果特别小
后来了解了装饰器模式,才了解到io模式也是主要用到这种模式进行设计的,所以如果从设计模式入手去理解这个io流的化,会明朗很多
从输入流 Inputstream出发
把他当作是基类的父接口,那么它下面的子实现类有:
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
这里挑一个最常用的
FileInputStream 作为讨论的基类,那么作为最基础的一个实现类,如果需求简单的话,传入系统文件路径就可以得到你要的文件输入流,然后可以根据里面实现的方法以及自定义的方法进行操作
但是这个可能达不到你的预期,你对文件流如果你要提高效率,你可能需要实现一种缓存,如果你需要对文件流特殊格式进行一种解压或者解析,可能需要额外在编写算法,当然这些java已经实现了,比如bufferedInputstream,GZIPInputStream等等
他们都继承于filterInputstream,额filterInputstream可以作为装饰类的一个标识,
定义了一个属性
protected volatile InputStream in;
通过最终传入进来的基类进行一层层的包装增强,最后得到符合需求的一个对象
我们尝试通过装饰模式自定义一个
package it.luke.decorator.ext;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author luke
* @Title: ${file_name}
* @Package ${package_name}
* @date 2020/7/200:39
*/
public class Mydec02 extends FilterInputStream {
FileInputStream fin;
/**
* Creates a <code>FilterInputStream</code>
* by assigning the argument <code>in</code>
* to the field <code>this.in</code> so as
* to remember it for later use.
*
* @param in the underlying input stream, or <code>null</code> if
* this instance is to be created without an underlying stream.
*/
protected Mydec02(InputStream in) {
super(in);
if(super.in instanceof FileInputStream){
fin=(FileInputStream) in;
};
}
public void readAdd123() throws IOException {
int read = fin.read();
System.out.println(read);
System.out.println(read+123);
// System.out.println(fin);
}
}
//97
//220
所读取的文件内容为"a"
可以看到针对读取后的字节码进行了修改操作,这样在调用fileinputstream的方法的基础上,还可以调用我们自己定义的方法…
};
}
public void readAdd123() throws IOException {
int read = fin.read();
System.out.println(read);
System.out.println(read+123);
// System.out.println(fin);
}
}
//97
//220
所读取的文件内容为"a"
可以看到针对读取后的字节码进行了修改操作,这样在调用fileinputstream的方法的基础上,还可以调用我们自己定义的方法..