zoukankan      html  css  js  c++  java
  • java设计模式4-装饰者模式

    什么是装饰者模式?

    在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

    重点理解一句话:动态的扩展一个对象的功能.

    我理解的装饰者模式:把一个东西用另一个东西来包装一下,以增加这个东西本身的功能.

    装饰者与继承的不同点.

    Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

    装饰者模式设计原则(了解):

    1,多用组合,少用继承.

       利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为.然而,如果有组合的做法扩展对象的行为,就可以运行进动态地进行扩展.

       在前面提到策略模式中也提到了,多用组合.那么策略模式装饰者有什么不一样的呢?

        1,装饰对象包含一个真实对象的引用,而策略模式里面持有的是同一类行为接口的引用.传入的时候是传入接口的实现类.

    2,类设计应该对扩展开放,对修改关闭.

    什么情况下要用装饰者模式.

    要添增加一个类的功能的时候,不能改变这个类的代码.

    javaIO典型的装饰者模式理解.

    超类输入流:InputStream

    两个分支:

      1个是主体的分支.FileInputStrean,StringBufferInputString,ByteArrayInputStrean.

      2,装饰者中间层,FilterInpuStrean

             BufferInputStrean DataInputStream LineNumberInputStrean

    现在我们要自己的扩展一个装饰者模式,大所有小写自动转成大写的流UpperCaseInputStream.

    package com.java.jikexueyuan.myiodecorator;
    
    import java.io.FilterInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    //直接继承分支的中间层.
    //因为分支的中间层已为我们设计好超类的引用
    public class UpperCaseInputStream extends FilterInputStream{
    
        //构造方法里面传入
        protected UpperCaseInputStream(InputStream in) {
            //可以用super是因了,FilterInputStream是一个分支的中间层
            super(in);        
        }
    
        //写自己的方法
        public int read() throws IOException
        {
            int c=super.read();
            return c==-1?c:Character.toUpperCase((char)(c));
        }
        public int read(byte[] b,int offset,int len) throws IOException
        {
            int result=super.read(b,offset,len);
            for(int i=0;i<result;i++)
            {
                b[i]=(byte)Character.toUpperCase((char)(b[i]));
            }
            
            return result;
        }
    }

    记住一点,每一个分支都要有中间成.用在作为装饰者类里面的引用

    装饰者模式怎么设计

    1,有一个抽象的超类,里面有抽象的方法,和一些共有属性字段信息.

    2,然后就是主体部分,主体部分可以理解成抽象超类的子类.主体类可以有一个中间层.

    //这是那个超类
    public abstract class Animal {
        //这是共有属性
        public String language;
        
        //get/set
        //共有的方法
        public abstract String  Speak();
        
    }
    
    //这个类就是那个中间层(这一层也可以省略)
    public class Human extends Animal {
    
        @Override
        public String Speak() {
            return super.language;
        }
    
    }
    //这是主体分支,就是超类的子类.当然还可以扩展出很子类出来.只举一个例子.
    public class Chinese extends Human {
    
        public Chinese(){
            super.language="汉语";
        }
        
        //这里是可以直接继承了Human类的Speak方法的.就要以不用在写了    
    }

    下面才是真正的装饰者的部分:

    1,同样要有一个中间层,(重点),主要就是这个中间层的设计.

    2,直接分支--直接改写方法,或添加方法.

    3,中间层这个类里面有一个超类的引用,通过构造方法传入(重点).

    中间层类直接 继承超类,里面有一个超类的引用从构造方法传入.

    然后就是一些自己的方法.

    要装饰的类直接继承这个中间者类.

    //功夫就是这个中间成.
    public class Gongfu extends Animal{
    
        Animal animal;
        Gongfu(Animal animal) {
            this.animal=animal;    
        }
    
        public void gongfu(){
            System.out.println("这个人会功夫");
        }
    
        是间层里面不用改变的方法直接调用父类来返回
        @Override
        public String Speak() {
            return animal.Speak();
        }    
    }
    
    //用功夫来装饰一个人
    public class Taiji extends Gongfu {
    
        //这个会自动生成,因为Gongfu没有无参的构造方法
        Taiji(Animal animal) {
            super(animal);
        }
        public void taiji(){
            System.out.println("这个人会taiji");
        }
    }

    这个代码有一点问题,没有时间去思考了.但是装饰者的大体思想这样.

  • 相关阅读:
    java使用google开源工具实现图片压缩
    MyBatis实现Mysql数据库分库分表操作和总结
    简单记录你博客园的访问人数
    细说spring事务配置属性
    hazelcast初探
    jstorm之于storm
    如何让其他机器访问你的oracle数据库
    问题解决:bash: fork: retry: Resource temporarily unavailable
    分布式锁的几种实现方式
    建立索引的原则总结
  • 原文地址:https://www.cnblogs.com/yinyu/p/5276694.html
Copyright © 2011-2022 走看看