设计模式——装饰模式

装饰模式

问题引入

现在有这样的两个类DrawColor并且这两个类有一个相同的方法draw

  • Draw负责画画
  • Color负责上色
  • 他们都使用draw方法来画画或者上色
class Draw {
    void draw() {
        System.out.println("画画");
    }
}

class Color {
    void draw() {
        System.out.println("上色");
    }
}

现在我要在画画的时候同时上色,有哪些方法可以完成?

实现方法

方式一 实例化一个需要的对象

只需要在其中的一个类的方法中实例化另一个类,调用该类的方法即可

public class Test01 {
    public static void main(String[] args) {
        Color color = new Color();
        // 可以实现同时画画和上色
        color.draw();
    }
}

class Draw {
    void draw() {
        System.out.println("画画");
    }
}

class Color {
    void draw() {
        Draw draw = new Draw();
        draw.draw();
        System.out.println("上色");
    }
}

这种方式的耦合度很高,需要更换就需要改代码

方式二 继承

只需要让其中的一个类继承另一个类,再调用父类的方法即可实现

public class Test01 {
    public static void main(String[] args) {
        Color color = new Color();
        // 同时画画和上色
        color.draw();
    }
}

class Draw {
    void draw() {
        System.out.println("画画");
    }
}

class Color extends Draw {
    @Override
    void draw() {
        // 使用父类中的方法画画
        super.draw();
        System.out.println("上色");
    }
}

这种方式的缺点是java只能单继承,如果需要继承其他的类就无法实现
这种方式的优点就是可以扩展JDK中的类

方式三 接口+构造器

  1. 将两个类中相同的方法放在接口中
  2. 让他们都实现这个接口
  3. 将这个接口作为构造器的参数
  4. 用的时候传入另一个对象即可
public class Test01 {
    public static void main(String[] args) {
        Color color = new Color(new Draw());
        color.draw();
    }
}

class Draw implements Work {
    @Override
    public void draw() {
        System.out.println("画画");
    }
}

class Color implements Work {
    Work work;

    public Color(Work work) {
        this.work = work;
    }

    @Override
    public void draw() {
        work.draw();
        System.out.println("上色");
    }
}

interface Work {
    void draw();
}

这种方式实现了解耦合,需要用哪个就通过构造器传哪个就行,不需要更改代码

方式四 成员变量+构造器

方式三虽然很不错,但是只在我们自己写的类中才能实现
如果要扩展jdk的类,我们不能更改源码,所以需要另一种方式

案例: 给BufferReader的read功能添加行号和字符统计的功能

public class Test02 {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(
                new FileReader("E:\\aaa.txt")
        );
        MyBufferReader myBufferReader = new MyBufferReader(reader);
        String s;
        while ((s = myBufferReader.readerLine()) != null) {
            System.out.println(s);
        }

        /*   运行结果:成功扩展
         *    1 aaaaaaa 字符数7
         *    2 bbbbbbb 字符数7
         *    3 ccccccc 字符数7
         *    4 ddddddd 字符数7
         */
    }
}

class MyBufferReader {

    private final BufferedReader reader;
    private static int lineCount = 1;

    public MyBufferReader(BufferedReader reader) {
        this.reader = reader;
    }

    public String readerLine() throws IOException {
        String s = reader.readLine();
        if (s == null) {
            return null;
        }
        return (lineCount++) + " " + s + " 字符数" + s.length();
    }
}

我们扩展的对象就是被装饰对象

也可以使用继承的方式来实现

public class Test02 {
    public static void main(String[] args) throws IOException {
        MyBufferReader myBufferReader = new MyBufferReader(
                new FileReader("E:\\aaa.txt")
        );
        String s;
        while ((s = myBufferReader.readerLine()) != null) {
            System.out.println(s);
        }
    }
}


class MyBufferReader extends BufferedReader {

    private static int lineCount = 1;

    public MyBufferReader(Reader in) {
        super(in);
    }


    public String readerLine() throws IOException {
        String s = super.readLine();
        if (s == null) {
            return null;
        }
        return (lineCount++) + " " + s + " 字符数" + s.length();
    }
}
posted @ 2021-12-07 17:16  茶音白  阅读(45)  评论(0)    收藏  举报