一、装饰者模式
当需要对已有的对象进行功能增强时,可以定义类(装饰类),将已有的对象传入,基于已有的功能,并提供加强功能,那么自定义的类成为装饰类
1.装饰模式和继承的区别:
相同点:
装饰模式与继承关系的目的都是要扩展对象的功能
不同点:
代码结构比继承更加简洁
饰模式可以提供比继承更多的灵活性(意味着可以向装饰器的构造方法传入被装饰类的子类对象)
2.继承是类与类或者接口与接口之间最常见的关系;继承是一种is-a关系
组合(Composition)体现的是整体与部分、拥有的关系,即has-a的关系
组合与继承的区别和联系:
1) 在继承结构中,父类的内部细节对于子类是可见的。所以我们通常也可以说通过继承的代码复用是一种白盒式代码复用。(如果基类的实现发生改变,那么派生类的实现也将随之改变。)
2) 组合是通过对现有的对象进行拼装(组合)产生新的、更复杂的功能。因为在对象之间,各自的内部细节是不可见的,所以我们也说这种方式的代码复用是黑盒式代码复用。(因为组合中一般都定义一个类型,所以在编译期根本不知道具体会调用哪个实现类的方法)
3) 继承,在写代码的时候就要指名具体继承哪个类,所以,在编译期就确定了关系。(从基类继承来的实现是无法在运行期动态改变的,因此降低了应用的灵活性。)
4) 组合,在写代码的时候可以采用面向接口编程。所以,类的组合关系一般在运行期确定。
在同等条件下,优先使用组合。
3.装饰者设计模式的特点:
装饰对象和真实对象有相同的接口或抽象类
装饰对象包含一个真实对象的引用
装饰对象接收所有的来自客户端的请求,它把这些请求转发给真实的对象
装饰对象可以在转发这些请求之前或之后增加一些附加的功能
4.装饰者设计模式的结构:
1) 抽象构建角色(Component):
给出一个抽象的接口,以规范准备接受附加责任的对象。相当于IO流里面的InputStream/OutputStream。
2) 具体的构建角色(ConcreteComponent):
定义一个将要接受附加责任的类。相当于IO里面的FileInputStream/FileOutputStream。
3) 抽象装饰角色(Decorator)
持有一个抽象构建角色(也就是Component)的引用,并实现这个与抽象构建接口。相当于FilterInputStream/FilterOutputStream。
4) 具体的装饰角色(ConcreteDecorator)
负责给构建对象“贴上”附加的责任。相当于BufferedInputStream/BufferedOutputStream。
package decorator;
/*
* 抽象构建角色
* */
public interface Love {
public void love(); //接口里的方法只声明,不实现
}
package decorator;
/*
* 具体构建角色
* */
public class Student implements Love{
@Override
public void love() {
System.out.println("学生正在谈恋爱...");
}
}
package decorator;
/*
* 抽象装饰角色
* */
public abstract class Decorator implements Love{
private Love love; // 持有抽象构建角色的引用
public Decorator(Love love){
this.love=love;
}
@Override
public void love() {
this.love.love();
}
}
package decorator;
/*
* 具体装饰角色
* */
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Love love){
super(love);
}
public void beautifulLove(){
System.out.println("送花...");
super.love();
System.out.println("结婚...");
}
}
package decorator;
import java.io.*;
public class Test {
public static void main(String[] args) {
Love love=new Student();
love.love();
System.out.println("********************");
ConcreteDecorator dec=new ConcreteDecorator(love);
dec.beautifulLove();
}
}
运行结果: