装饰(包装)模式
看黑马视频时看到数据源实现时用的装饰者模式改写了close方法(实际上java里IO流是典型的装饰模式),于是学习了下装饰模式
主要参考了网上其他人的例子,自己把别人的进行了简化记录下来(非原创),便于以后温习。
适用性:
1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
设计原则:
1. 多用组合,少用继承。
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
2. 类应设计的对扩展开放,对修改关闭。
设计步骤:
a、编写一个类实现与被改写类相同的接口
b、定义一个引用,记住被改写类的实例
c、定义构造方法,传入被改写类的实例
d、对于要改写的方法,改写即可
e、对于不需要改写的方法,调用原有的对象的对应方法
c、定义构造方法,传入被改写类的实例
d、对于要改写的方法,改写即可
e、对于不需要改写的方法,调用原有的对象的对应方法
示例代码:
接口
public interface Component { public void sampleComponent(); public void close(); }
实现类
public class ConcreteComponent implements Component { public void sampleComponent() { System.out.println("ConcreteComponent"); } public void close(){ System.out.println("close"); } }
假设需要修改sampleComponent方法,但是不能在原有的类上修改(很简单,比如你用的别人的jar包如数据库驱动包,肯定是不允许你在原有代码上修改的),这是就可以用继承和装饰模式来修改。
若没有接口类只有一个ConcreteComponent类时可以直接使用继承。但有实现接口时,考虑下如果你使用的框架有一个方法要求你传入的参数必须为Component接口类型,如果你使用继承添加(是添加不是修改)了一个方法,那么利用多态机制将继承类作为参数传入框架中的方法是无法使用添加的这个方法的,那继承的意义何在呢?
装饰类
public class Decorator implements Component{ public Component component; public Decorator(Component component) { this.component = component; } public void sampleComponent() { System.out.println("Decorator"); } public void close() { component.close(); } }
这样就改写了原有的sampleComponent()方法,可以将装饰类传入框架中的方法,相比于继承要灵活不少。
测试
public class Test6{ public void aa(){ System.out.println("aa"); } public static void main(String[] args) throws SQLException { Component component=new ConcreteComponent(); Decorator decorator=new Decorator(component); decorator.sampleComponent(); decorator.close(); } }
这样既修改了原来的sampleComponent()方法也能使用原有的方法,实现了对类的功能的扩展。