面向对象的设计模式(二)——Decorator模式

(二)“单一职责”模式

在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键就是划清责任。

1.  Decorator 装饰模式

◆  动机:
        在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
        如何使“对象功能的扩展”能够根据需要来动态实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低?

首先,用代码举一个例子,这是一个操作数据流的类:
//业务操作
abstract class Stream {
    public abstract char read(int number);

    public abstract void seek(int position);

    public abstract void write(char data);

}

//主体类
class FileStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //***********
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //***********
    }

    //写文件流
    @Override
    public  void write(char data){
        //***********
    }

}

class NetworkStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //###########
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //###########
    }

    //写文件流
    @Override
    public  void write(char data){
        //###########
    }
}


class MemoryStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //@@@@@@@@@@@

    }

    //定位文件流
    @Override
    public  void seek(int position){
        //@@@@@@@@@@@
    }

    //写文件流
    @Override
    public  void write(char data){
        //@@@@@@@@@@@
    }
}



//扩展操作
class CryptoFileStream extends FileStream {

    @Override
    public char read(int number) {
        //额外的加密操作...

        //读文件流
        super.read(number);

    }

    @Override
    public void seek(int position) {
        //额外的加密操作...

        //定位文件流
        super.seek(position);

        //额外的加密操作...

    }

    //写内存流
    @Override
    public void write(char data) {
        //额外的加密操作...

        //写文件流
        super.write(data);

        //额外的加密操作...
    }
}

class CryptoNetworkStream extends NetworkStream {


    @Override
    public char read(int number) {
        //额外的加密操作...

        //读网络流
        super.read(number);
    }

    @Override
    public void seek(int position) {
        //额外的加密操作...

        //定位网络流
        super.seek(position);

        //额外的加密操作...
    }


    @Override
    public void write(char data) {
        //额外的加密操作...

        //写网络流
        super.write(data);

        //额外的加密操作...
    }
}


class CryptoMemoryStream extends MemoryStream {


    @Override
    public char read(int number) {
        //额外的加密操作...

        //读内存流
        super.read(number);
    }

    @Override
    public void seek(int position) {
        //额外的加密操作...

        //定位内存流
        super.seek(position);

        //额外的加密操作...
    }

    //写内存流
    @Override
    public void write(char data) {
        //额外的加密操作...

        //写内存流
        super.write(data);

        //额外的加密操作...
    }
}


class BufferedFileStream extends FileStream {

}

class BufferedNetworkStream extends NetworkStream {

}

class BufferedMemoryStream extends MemoryStream {

}

class CryptoBufferedFileStream extends FileStream {


    @Override
    public char read(int number) {
        //额外的加密操作...
        //额外的缓冲操作...

        //读文件流
        super.read(number);

        //额外的加密操作...
        //额外的缓冲操作...

    }

    @Override
    public void seek(int position) {
        //额外的加密操作...
        //额外的缓冲操作...
        //定位文件流

        super.seek(position);

        //额外的加密操作...
        //额外的缓冲操作...
    }

    @Override
    public void write(char data) {
        //额外的加密操作...
        //额外的缓冲操作...

        //写文件流
        super.write(data);
        
        //额外的加密操作...
        //额外的缓冲操作...
    }
}


class Client {

    public static void main(String args[]) {

        //编译时装配
        CryptoFileStream fs1 = new CryptoFileStream();

        BufferedFileStream fs2 = new BufferedFileStream();

        CryptoBufferedFileStream fs3 = new CryptoBufferedFileStream();

    }
}
代码的结构逻辑如下图,这样的数据机构会生成很多很多子类。注意,crypto、Bufferde这些方法是要在FileStream、NetwodStream等对象的基础上才能实现的。FileStream这些类叫做“主体类”,CryptoFileStream这些类叫做“扩展类”,

利用Decorator模式进行优化,优化后代码如下:
//业务操作
abstract class Stream {
    public abstract char read(int number);

    public abstract void seek(int position);

    public abstract void write(char data);

}

//主体类
class FileStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //***********
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //***********
    }

    //写文件流
    @Override
    public  void write(char data){
        //***********
    }

}

class NetworkStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //###########
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //###########
    }

    //写文件流
    @Override
    public  void write(char data){
        //###########
    }
}


class MemoryStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //@@@@@@@@@@@

    }

    //定位文件流
    @Override
    public  void seek(int position){
        //@@@@@@@@@@@
    }

    //写文件流
    @Override
    public  void write(char data){
        //@@@@@@@@@@@
    }
}



//继承:接口协议
class CryptoStream extends Stream  {

    /**
     *  组合:复用实现
     */
    Stream s;// s=new FileStream(); s=new NetworkStream(); s=new MemoryStream();
             // 在子类中以父类的实例作为一个成员变量,这是典型的decrorator模式

    /**
     * 通过构造函数传递一个具体的类型进来
     */
    public CryptoStream(Stream s)
    {
        this.s=s;
    }

    @Override
    public char read(int number) {
        //额外的加密操作...

        //读文件流
        s.read(number);

    }

    @Override
    public void seek(int position) {
        //额外的加密操作...

        //定位文件流
        s.seek(position);

        //额外的加密操作...

    }

    //写内存流
    @Override
    public void write(char data) {
        //额外的加密操作...

        //写文件流
        s.write(data);

        //额外的加密操作...
    }
}


class BufferedStream extends Stream {
    Stream s;

    public BufferedStream(Stream s)
    {
        this.s=s;
    }
}


class Client {

    public static void main(String args[]) {

        //运行时装配

        Stream s1=new CryptoStream( new FileStream());

        Stream fs2 = new BufferedStream(new FileStream());

        Stream fs3 = new CryptoStream(new BufferedStream(new FileStream()));


    }
}
这样,Decorator模式基本上已经算完成了,不过我们还可以再进行一个小优化:
//业务操作
abstract class Stream {


    public abstract char read(int number);

    public abstract void seek(int position);

    public abstract void write(char data);

}

//主体类
class FileStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //***********
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //***********
    }

    //写文件流
    @Override
    public  void write(char data){
        //***********
    }

}

class NetworkStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //###########
    }

    //定位文件流
    @Override
    public  void seek(int position){
        //###########
    }

    //写文件流
    @Override
    public  void write(char data){
        //###########
    }
}


class MemoryStream extends Stream {
    //读文件流
    @Override
    public  char read(int number){
        //@@@@@@@@@@@

    }

    //定位文件流
    @Override
    public  void seek(int position){
        //@@@@@@@@@@@
    }

    //写文件流
    @Override
    public  void write(char data){
        //@@@@@@@@@@@
    }
}

/**
 * 一个基类,用于提取CryptoStream和BufferedStream共同的成员变量s
 * 因为这个类没有继承父类所有属性,所以是抽象类
 * 根据重构的原则,继承自同一父类的几个子类含有相同的字段或变量时,应该把它往上提,
 * 而直接放在Stream类里面的话,会影响FileStream、MemoryStream等类的使用,所以我们就要一个基类实现重构
 */
//继承:接口协议
abstract  DecroratorStream extends Stream{
    //组合:复用实现
    protected Stream s;// s=new FileStream(); s=new NetworkStream(); s=new MemoryStream();

    protected DecroratorStream(Stream s){
        this.s=s;
    }
}


class CryptoStream extends DecroratorStream  {


    public CryptoStream(Stream s)
    {
        //改为继承父类的方法
        super(s);
    }

    @Override
    public char read(int number) {
        //额外的加密操作...

        //读文件流
        s.read(number);

    }

    @Override
    public void seek(int position) {
        //额外的加密操作...

        //定位文件流
        s.seek(position);

        //额外的加密操作...

    }

    //写内存流
    @Override
    public void write(char data) {
        //额外的加密操作...

        //写文件流
        s.write(data);

        //额外的加密操作...
    }
}

class BufferedStream extends DecroratorStream {
    Stream s;

    public BufferedStream(Stream s)
    {
        super(s);
    }

    //....
}


class Client {

    public static void main(String args[]) {

        //运行时装配

        FileStream fs=new FileStream();

        Stream s1=new CryptoStream( new FileStream());

        Stream s2 = new BufferedStream(new FileStream());

        Stream s3 = new CryptoStream(new BufferedStream(new FileStream()));


    }
}
现在逻辑结构如下图,可以看到,我们的代码结构简洁了很多!

◆  模式定义:
        动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活(消除重复代码&减少子类个数)。
◆  要点总结:
        ●  通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”;
        ●  Decorator类在接口上表现为 is-a Component的继承关系,即Decorator类继承了Component类所有的接口。但在实现上又表现为 has-a Component的组合关系,即Decorator类又使用了另一个Component类。这就是Decorator模式的典型特征;(见下图)

        ●  Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主题类在 多个方向上的扩展功能” —— 是为“装饰”的含义;









1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值