再战设计模式(十)之装饰模式

装饰模式

职责:

动态的为一个对象添加新的功能

装饰模式i是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀

  现在假设:有一辆汽车 ,我们需要他实现 会飞,会游泳,会自动驾驶的功能,我们没有用设计模式之前应该是 定义一个接口,定义3个子类去实现. 那么我现在有需要他既会飞又会游泳呢?是不是还需要继续实现和extends

如果现在要求3种都会呢?那么我们是不是需要继续extends 

现在我们用装饰模式来实现下这的功能

类图如下:

 

 代码:

/**
 * compent 组件 具有真实对象和 装饰对象相同的接口,这样
 * 客户端可以和真实的对象一样和装饰对象交互
 */
public interface CarComponent {
    void move();
}
/**
 * 真实的类
 */
public class Car implements CarComponent {
    @Override
    public void move() {
        System.out.println("真实的汽车");
    }
}
/**
 * 装饰的类
 */
public class DecoratorCar implements CarComponent{

    protected CarComponent carComponent;

    public DecoratorCar(CarComponent carComponent) {
        this.carComponent = carComponent;
    }

    @Override
    public void move() {
        carComponent.move();
    }
}

public class FlyCar extends DecoratorCar {
    public FlyCar(CarComponent carComponent) {
        super(carComponent);
    }

    public void fly(){
        System.out.println("汽车飞起来了");
    }

    @Override
    public void move() {
      super.move();
      fly();
    }
}

public class WaterCar extends DecoratorCar {

    public WaterCar(CarComponent carComponent) {
        super(carComponent);
    }

    public  void swim(){
        System.out.println("i'm siwmming ");

    }
    @Override
    public void move() {

      super.move();
    swim();
    }
}




public class AICar extends DecoratorCar {
    public AICar(CarComponent carComponent) {
        super(carComponent);
    }

    public  void ai(){
        System.out.println("auto move car");
    }
    @Override
    public void move() {
       super.move();
       ai();
    }
}


public class Clinet {

    public static void main(String[] args) {

        CarComponent car = new Car();
        car.move();

        DecoratorCar car1 = new DecoratorCar(new FlyCar(car));
        car1.move();
        System.out.println("水车和ai组合===============");

        DecoratorCar car2 = new WaterCar(new AICar(car));
        car2.move();
    }
}

 

现在我们有3个子类,分别会飞  会游泳  会自动驾驶,,现在我们把他们组合一下,让一个简单得汽车用这几个功能

 

public class Clinet {

    public static void main(String[] args) {

        CarComponent car = new Car();

        System.out.println("fly swim ai auto--------------------------");

        DecoratorCar car2 = new WaterCar(new AICar(new FlyCar(car)));
        car2.move();
    }
}

就这么简单就可以了.如果不适用这样的模式的话,我们有俩种办法 1. 新建一个类 他继承 会飞 会游泳的,会自动驾驶的,或者实现一个接口 把这3个都写进行,但是这样的话不够灵活,不易扩展

实现细节

component: 抽象构建角色

真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互 

ConcreteComponent 具体构件角色(真实对象) :
真实的对象

Decorator装饰角色
他持有了一个构建角色的引用,装饰对象接受对客户端的请求,并发这样请求转发给真实的对象,这样就可以在真实的对象前后实现自己的逻辑

concreteDecorator角色

负责给对象添加新的功能

 

总结

装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新

的具体构建类和具体装饰类

优点:

1. 扩展对象比继承灵活,不会导致类个数急剧增加

2. 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象 

3具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类

缺点:

 产生很多小对象,大量的小对象占据内存,一定程度上影响性能

装饰模式出错的话,调试排查比较麻烦

对比:

装饰模式和桥接模式的区别

两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。桥 模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。装饰模式是为了增加新的功能

和代理模式对比

代理模式是在一个方法上添加将相同的操作提取出去,装饰模式是,增加新的功能

 

jdk中用到的地方:

IO流我随意找了一个地方就.大家可以看看类图

 

posted @ 2019-05-13 11:05  北京de小刀  阅读(186)  评论(0编辑  收藏  举报