zoukankan      html  css  js  c++  java
  • 设计模式之装饰(Decorator)模式

    设计模式之装饰(Decorator)模式

    (一)什么是装饰(Decorator)模式

      装饰模式,又称为包装模式,它以对客户端透明的方式扩张对象的功能,是继承关系的替代方案之一。
      装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

    (二)装饰模式的角色

      1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象
      2)具体构件(Concrete component)角色:定义一个将要接受附加责任的类
      3)装饰角色(Decorator)角色:持有一个构建(Component)对象的实例
      4)具体装饰(Concrete decorator)角色:负责给构件对象添加功能。

    (三)装饰模式的实现

      想象一下这样一种情况,定义了一个接口Car(代码如下),里边只包含一个方法move(),这个方法用来展示具体车的移动方式。

    public interface Car {
        void move();
    }

      首先我们创建一个最普通的车RunCar(这里的普通指的是移动方式为陆地移动),实现这个接口。

    public class RunCar implements Car {
    
        @Override
        public void move() {
            this.run();
        }
        
        public void run() {
            System.out.println("可以跑");
        }
        
    }

      随着科技的进步,可能会有能够飞的车FlyCar,可能会有SwimCar,我们首先想到的实现方式就是继承,通过子类的实现扩展父类的功能,在这里指的是分别创建FlyCar类和SwimCar类实现Car接口。如果有这样一种需求,创建一种既能飞fly也能swim的FlySwimCar,这样该如何实现的,传统的继承能够实现,但一方面java只支持单继承,灵活性较差,另一方面,之前已经分别创建了FlyCar和SwimCar,如果再创建FlySwimCar会造成代码重复,想象一下,如果能够在FlyCar的基础上扩展swim功能就好了。

      恰巧,装饰着模式就能解决此类问题。

      这里我们的Component角色 指的就是Car接口,它既是被装饰类的父接口,也是装饰类的父接口。

      RunCar扮演的就是被装饰者的角色,它是Component角色的实现类。

      抽象装饰角色为CarDecorator,实现了Car接口,切内部包含一个Car的引用,用来保存被装饰的对象:

    public abstract class CarDecorator implements Car  {
        private Car car;
        public CarDecorator(Car car) {
            this.car = car;
        }
        
        
        public Car getCar() {
            return car;
        }
    
    
        public void setCar(Car car) {
            this.car = car;
        }
    
    
        public abstract void move();
    } 

      具体抽象角色用于具体功能的扩展,在这里SwimCarDecorator为传进的汽车对象增加swim功能,FlyCarDecorator为传进的汽车对象增加fly功能。

    public class SwimCarDecorator extends CarDecorator {
    
        public SwimCarDecorator(Car car) {
            super(car);
        }
        
        public void move() {
            this.getCar().move();
            this.swim();
        }
        
        public void swim() {
            System.out.println("可以游");
        }
    
    }
    public class FlyCarDecorator extends CarDecorator {
    
        public FlyCarDecorator(Car car) {
            super(car);
        }
    
        @Override
        public void move() {
            this.getCar().move();
            this.fly();
        }
        
        public void fly() {
            System.out.println("可以飞");
        }
        
    }

      这样以来,如果要创建一个会飞的汽车,那么把一个普通汽车传给FlyCarDecorator即可,如果创建一个会swim的车,把普通汽车传给SwimDecorator即可,如果想创建一个既会fly也会swim,只需把一个普通对的车传给FlyCarDecorator,再传给SwimDecorator即可。

    public class Client {
        public static void main(String[] args) {
            Car runCar = new RunCar();
            runCar.move();
            System.out.println("-----------");
            Car flyCar = new FlyCarDecorator(runCar);
            flyCar.move();
            System.out.println("-----------");
            Car flySwimCar = new SwimCarDecorator(new FlyCarDecorator(new RunCar()));
            flySwimCar.move();
        }
    }

    (四)在什么情况下使用装饰模式

      需要扩展一个类的功能,或给一个类增加附加责任。
      需要动态地给一个对象增加功能,这些功能可以动态的撤销
      需要增加由一些基本功能排列则和而产生的非常大量的功能,从而使继承关系变得不显示。

    (五)装饰模式的简化

      1)如果只有一个ConcreteComponent类而没有抽象的Component接口,可以把Decorator类设为ConcreteComponent的一个子类  
      2)如果只有一个ConcreteDecorator类,就没有必要定义Decorator类

    (六)装饰模式的优缺点  

      优点:
        1)装饰模式与继承关系的目的都是扩展对象的功能,装饰模式可以提供比继承更多的灵活性。继承是静态的,而装饰是动态的。
        2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可是设计出很多不同行为的组合。
      缺点:
       使用装饰比使用继承需要更少数目的类,使用较少的类当然设计比较易于进行,但另一方面,装饰模式会产生比继承关系更多的对象,这些对象看上去都很相似,因此查错更为困难。

      总结:装饰者模式:是你还有你,多数拜托你

  • 相关阅读:
    四则运算
    3.12----对potplayer的使用评价
    对软件工程的一点思考
    个人附加作业
    附加题
    个人最终总结
    结对编程总结
    修改后的四则运算
    阅读程序回答问题
    Visual studio 2013的安装和单元测试
  • 原文地址:https://www.cnblogs.com/gdy1993/p/9193841.html
Copyright © 2011-2022 走看看