读前辈的大话设计模式(四)之装饰模式,抒自己的读后感

    装饰模式(Decorator Pattern):动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

    装饰模式结构:

    ①.Component: 定义一个对象接口,可以给这些对象动态的添加职责,也叫抽象的Component;

    ②.ConcreteComponent:定义了一个具体的对象,也可以给这个对象添加一些职责,继承Component,也叫具体的Component;

    ③.Decorator:装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无须知道Decorator的存在的。

    ④.ConcreteDecorator:具体的装饰对象类,起到给Component添加职责的功能,继承Component,并且可以有多个。

     核心思路: 我们把需要展示的功能按预期的顺序串联起来进行控制。

     正如书中小菜的疑惑那样,当需求中看起来并没有执行类必须定义成接口或者抽象类时,是不是上面的结构模式就被破坏?大鸟给出了很好的建议,如果只有一

    个 ConcreteComponent类,那么Decorator类可以是ConcreteComponent的一个子类,同样道理,如果只有一个ConcreteDecorator,那么就没有必要再建立一个单独

     的 Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

     这里说的是一种替代思想,也就是里氏代换原则:一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且他察觉不到父类对象和子类对象的区别,也就是说在软件里把父类都替换成他的子类,程序的行为没有发生变化,即子类必能够替换他们的父类型。也就是说,我们用子类也能实现对应的功能。

    好了,我们接下来试一下代码吧,也许看完代码你就豁然开朗。

    本文依旧用 Java 来完成代码的展示。

    1、顺着书中的意思:我们直接定义一个ConcreteComponent类:

package controller;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

/**
 * Created by Administrator on 2017/8/2.
 */
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    private String name;

    public void display(){
        System.out.println("是"+ name + "今天的打扮");
    }
}

     2、定义一个ConcreteDecorator 总类(看清楚这里说的是总类) Dress,这个类原本应该继承Decorator,且Decorator继承Component,现在Component没有了,也不需要再定义Decorator了,所以直接继承Component的子类ConcreteComponent,在这里我们就需要继承Person这个类:

package operation;

import controller.Person;

/**
 * Created by Administrator on 2017/8/2.
 */
public class Dress extends Person {

    Person component;

    /**
     * 装饰模式的核心:找模特进行装饰
     * @param component 模特
     */
    public void decorate(Person component){
        this.component = component;
    }

    /**
     * 重写display(),实际上执行的是 Person 的 dispplay()---  component.display();
     */
    @Override
    public void display(){

        if (null != component){
            component.display();
        }
    }

}

 

   3、分别定义多个ConcreteDecorator 分类(看清楚这里说的是分类),分类直接继承总类 Dress即可:

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class BlackClothes extends Dress {

    @Override
    public void display() {
        System.out.println("黑色的衣服");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class GrayShoes extends Dress {

    @Override
    public void display() {
        System.out.println("灰色的鞋子");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class GrayTrousers extends Dress {

    @Override
    public void display() {
        System.out.println("灰色的长裤");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class RedClothes extends Dress {

    @Override
    public void display() {
        System.out.println("红色的衣服");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class RedShoes extends Dress {

    @Override
    public void display() {
        System.out.println("红色的鞋子");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class WhiteClothes extends Dress {

    @Override
    public void display() {
        System.out.println("白色的衣服");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class WhiteShoes extends Dress {

    @Override
    public void display() {
        System.out.println("白色的鞋子");
        super.display();
    }
}

package entity;

import operation.Dress;

/**
 * Created by Administrator on 2017/8/2.
 */
public class WhiteTrousers extends Dress {

    @Override
    public void display() {
        System.out.println("白色的长裤");
        super.display();
    }
}

   

     4、至此,需要做的准备工作已经完成,接下来测试,也就是装饰及展示效果的过程,定义测试类:

import controller.Person;
import entity.*;
import operation.Dress;
import org.junit.Test;

/**
 * Created by Administrator on 2017/8/2.
 */
public class TestDress {
    @Test
    public void testDress(){

        /**
         * 模特出来了,二哥,初始状态没有装饰
         */
        Person pp = new Person("二哥");

        WhiteClothes whiteClothes = new WhiteClothes();
        GrayTrousers grayTrousers = new GrayTrousers();
        WhiteShoes whiteShoes = new WhiteShoes();

        /**
         * 装饰过程,把衣物一件件装饰到模特身上
         * 可以看到,核心就是装饰品找模特进行装饰的过程
         */
        whiteClothes.decorate(pp);
        grayTrousers.decorate(whiteClothes);
        whiteShoes.decorate(grayTrousers);

        /**
         * 后台已经打扮完成,出来展示效果了
         */
        whiteShoes.display();

    }
}

    展示效果如下:


    装饰模式总结:

    适用需求描述:当系统需要新功能的时候,是向旧的类中添加新的代码,这些新添加的代码,通常装饰了原有类的核心职责或者主要行为,这种在主类中增加新字段,新方法,新逻辑的做法增加了主类的复杂度,然而,这心新添加的内容仅仅是为了满足一些或者某种情况的使用,让主类没有选择的机会。

    装饰模式是为已有功能动态的添加更多功能的一种方式。他把每个需要装饰的功能放在单独的类中,并让这个类包装他所要的装饰对象,因此当需要使用特殊需求时,客户代码就可以在运行时有选择的,按顺序的使用装饰功能包装对象,相当于放宽了条件让你自由选择。

    装饰模式的优点:把类中的装饰功能从类中搬移出去,这样可以简化原有的类,并且把类的核心职责和装饰功能分开了,同时去除相关类中的重复装饰的逻辑。

    相当于在本例中,造了一大批分类继承Dress这个总类,而不是直接在Dress这个总类中写所有的。


    好了,到此,装饰模式基本结束。

   



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值