装饰者模式之通俗易懂

1、是什么

一句话:需要包装,但不改变本质(同宗同源)。

在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)
特点:
1、注重覆盖、扩展。
2、装饰器和被装饰器都实现同一个接口,主要目的是为了扩展之后依旧保留 OOP 关系(同宗同源)。
3、满足 is-a 的关系。

2、有什么用?

扩展一个类的功能或者给一个类添加附加职责
给一个对象动态的添加功能,或动态撤销功能。

IO 流包装

FilterInputStream filterInputStreasm = new BufferedInputStream(new FileInputStream(new File("/user/a")));

前台表单页面填写中文,通过servlet请求传递到后台,如果不经过任何处理,前台默认通过UTF-8编码,后台默认iso-8859-1解码,编码方式的差异难免造成乱码问题,可以用装饰者模式处理该问题。

数据源包装
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每 次访问中根据需要会去访问不同的数据库。我们以往在 Spring 和 Hibernate 框架中总是配置一个数据 源,因而 SessionFactory 的 DataSource 属性总是指向这个数据源并且恒定不变,所有 DAO 在使用 SessionFactory 的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的 DAO 在 访 问 SessionFactory 的 时 候 都 不 得 不 在 多 个 数 据 源 中 不 断 切 换 , 问 题 就 出 现 了 : 如 何 让 SessionFactory 在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能 在 Spring 的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢? 首先想到在 Spring 的 ApplicationContext 中配置所有的 DataSource。这些 DataSource 可能是各 种不同类型的,比如不同的数据库:Oracle、SQL Server、MySQL 等,也可能是不同的数据源:比如 Apache 提 供 的 org.apache.commons.dbcp.BasicDataSource 、 Spring 提 供 的 org.springframework.jndi.JndiObjectFactoryBean 等。然后 SessionFactory 根据客户的每次 请求,将 DataSource 属性设置成不同的数据源,以到达切换数据源的目的。 Spring 中用到的包装器模式在类名上有两种表现:一种是类名中含有 Wrapper,另一种是类名中含有 Decorator。基本上都是动态地给一个对象添加一些额外的职责。

简历包装

3、怎么用?

一般当我们需要在具体的类中都需涛执行一些特定的操作时。我们一般就会使用抽象类,并定义抽象方法。

要点:
(1)抽象组件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
(2)被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体对象。
(3)装饰者组件(Decorator):持有组件对象的实例引用,该类的职责就是为了装饰具体组件对象,定义的基类。
(4)具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能。

总结起来就是,如果想对一个行为在不改变原来基础上加新功能和扩展,首先先把该行为抽象出来。然后实现抽象行为,原来的行为具体实现该抽象行为,创建一个抽象行为也实现同一个抽象行为,如果要装饰的时候,再在具体实现该装饰抽象类。

使用案例:

绞尽脑筋想不到很好的案例,网上很多其他的案例可以参考,但大部分都是卖东西

下面就结合自身写个案例吧
作为一名技术宅程序员,166的身高普通的样貌,不善言辞的嘴巴,至今一直单身,家里人为止着急上火,本人也很无奈,被嫌弃太多,习惯成自然,以后要自信。

下面用装饰模式给自己装饰一番,看魅力值有没有提高半分。

开撸:

//原来抽象 的我

public interface AbstractMyself {
    //身高
    public long getHeight();

    //样貌
    public String getAppearance();

    //言谈
    public String getSpeech();
}

//原來的我

public class Myself implements AbstractMyself {
    @Override
    public long getHeight() {
        return 166;
    }

    @Override
    public String getAppearance() {
        return "普通";
    }

    @Override
    public String getSpeech() {
        return "不善言辞";
    }
}

//抽象装饰后的我

public abstract class AbstractDecorator implements AbstractMyself {

    private AbstractMyself abstractMyself;

    public AbstractDecorator(AbstractMyself abstractMyself) {
        this.abstractMyself = abstractMyself;
    }

    @Override
    public long getHeight() {
        return this.abstractMyself.getHeight();
    }

    @Override
    public String getAppearance() {
        return this.abstractMyself.getAppearance();
    }

    @Override
    public String getSpeech() {
        return this.abstractMyself.getSpeech();
    }
}

//具体装饰后的我

/**
 * 提升后的我
 */
public class PromoteMyself extends AbstractDecorator {

    public PromoteMyself(AbstractMyself myself) {
        super(myself);
    }

    //穿增高鞋
    @Override
    public long getHeight() {
        return super.getHeight() + 8;
    }

    @Override
    public String getAppearance() {
        return "保养皮肤";
    }

    @Override
    public String getSpeech() {
        return "多读书,多当众讲话";
    }
}

//测试

public class Test {
    public static void main(String[] args) {
        //原来的我
        AbstractMyself myself = new Myself();
        System.out.println(myself.getAppearance() + myself.getSpeech() + myself.getHeight());
        //裝飾后的我
        PromoteMyself promoteMyself = new PromoteMyself(myself);
        System.out.println(promoteMyself.getAppearance() + promoteMyself.getSpeech() + promoteMyself.getHeight());

    }
}

装饰者模式之通俗易懂_第1张图片

你可能感兴趣的:(设计模式)