zoukankan      html  css  js  c++  java
  • Java设计模式-装饰器模式

    装饰器设计模式顾名思义就是装饰某个对象,让一个功能单一的对象拥有一些其他的功能,这些功能的添加是动态的。用户可以随意的扩展原有对象的功能。一方面代替了继承,相对于继承带来的功能扩展,装饰器模式可以理解为动态的扩展,用户需要什么就扩展什么功能,非常灵活,而继承带来的缺点就是不方便修改,是静态的扩展。由于他的方便也带来了缺点,在装饰的过程中,其实创建了很多的对象占据内存资源,这些对象大多都很相似,排查错误也是有很大困难。


    比如有一根电线,现在只有铜丝,只不过现在只能导电,我们在他的外面加一层绝缘体比如橡胶,这样他在导电的同时还安全了,外部具有绝缘的功能。


    装饰器模式中有一个抽象的对象,定义为接口,为什么这么定义呢,这里的例子是电脑的例子,先定义一个基本的电脑,他可以是笔记本电脑,台式电脑,平板电脑等等,但是他们都有相同的基本信息,他们有名字,有价格。我们定义所有电脑基本的抽象方法(更像是一种规范),后期如果有新式的电脑出现,新的名字,新的价格出现,最基本的是这些。

    package demo_dectorator;
    
    public interface AbstractComputer {
        public abstract String name();
    
        public abstract double price();
    }
    


    下面是一个对接口的实现,也是对抽象产品的具体化,这个实现可能会有很多,有恨多品牌名字价格的电脑,也是为什么要定义一个抽象类或者接口。假设电脑的基本价格是3000,名字叫做普通电脑。

    package demo_dectorator;
    
    public class Computer implements AbstractComputer{
    
    
        @Override
        public String name() {
            return "普通电脑";
        }
    
        @Override
        public double price() {
            return 3000;
        }
    
    
    }
    

    下面我们对这个电脑进行改进,我们要在电脑里加内存条,增大运行内存。定义一个抽象的原件类,同样实现接口,为什么这样呢?

    装饰者模式必然有一个公共的接口或抽象类,用来作为对象的传递。你需要根据接口实现基本的被装饰类,以及装饰类的公共接口,以后所有的装饰类都是继承自公共的装饰类接口,内部实现。

    在逻辑上也是可以说的过去的,电脑配件依附于电脑,拥有和电脑一样的属性。

    package demo_dectorator;
    
    public abstract class Device implements AbstractComputer{
    
    
        public abstract String name();
    
        public abstract double price();
    }
    

    接下来具体要装饰的内容

    package demo_dectorator;
    
    /*内存类*/
    
    public class Memory extends Device{
    
        public AbstractComputer computer;
    
        public Memory(AbstractComputer computer) {
            this.computer = computer;
        }
    
        public String name() {
            return computer.name() + "加内存";
        }
    
        public double price() {
            return computer.price() + 300;
        }
    
    }
    

    package demo_dectorator;
    
    /*硬盘类*/
    
    public class HardDisk extends Device{
        public AbstractComputer computer;
    
        public HardDisk(AbstractComputer computer) {
            this.computer = computer;
        }
    
        public String name() {
            return computer.name() + "加硬盘";
        }
    
        public double price() {
            return computer.price() + 500;
        }
    }
    

    在装饰的过程中最重要的就是子类继承父类,在执行子类的构造方法的时候,会隐式调用super(),如下

    public Memory(AbstractComputer computer) {
            super();
            this.computer = computer;
        }

    public HardDisk(AbstractComputer computer) {
            super();
            this.computer = computer;
        }

    接下来写测试类

    package demo_dectorator;
    
    /*
    * 客户类,测试装饰器模式*/
    
    public class Client {
        public static void main(String[] args) {
    
            Computer computer = new Computer();
    
            HardDisk h = new HardDisk(computer);
            System.out.println(h.name());
            System.out.println("价格:"+h.price());
    
            Memory m = new Memory(computer);
            System.out.println(m.name());
            System.out.println("价格:"+m.price());
    
            HardDisk h1=new HardDisk(m);
            System.out.println(h1.name());
            System.out.println("价格:"+h1.price());
    
    
        }
    }
    

    输出结果

    普通电脑加硬盘
    价格:3500.0
    普通电脑加内存
    价格:3300.0
    普通电脑加内存加硬盘
    价格:3800.0

    装饰器模式很好的体现开闭原则:对于扩展是开放的,对于修改是关闭的。用户可以动态添加功能。在java的io流中也是应用了装饰器模式。

  • 相关阅读:
    MarkDown使用教程
    B+树详解
    B-树(B树)详解
    SQL优化之limit 1
    mysql explain用法和结果的含义
    MySQL 常用内置函数与所有内置函数
    Mac os 相关查找命令
    数据库——自然连接、内连接、外连接(左外连接、右外连接,全连接)、交叉连接
    sql语句执行顺序
    有三个线程,怎么让他们按顺序执行?
  • 原文地址:https://www.cnblogs.com/duzhentong/p/7816585.html
Copyright © 2011-2022 走看看