《Head First 设计模式》 - 装饰模式

2020-04-10 11:24:39 浏览数 (3)

前言: 前沿技术一直在迭代,有一种东西是不会更新的,那就是设计模式的思想。 可以来学习学习设计模式的思维,巧妙设计!

一、官方话语概述六大原则二、个人解读概述六大原则三、今日主题场景概述相关代码抽象元组件产品被装饰者抽象装饰者组件产品装饰者测试四、读者须知

一、官方话语

概述

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。

六大原则

  1. 单一职责原则 (Single ResponsiBility Principle) 概括:应该有且仅有一个原因引起类的变更
  2. 里氏替换原则(liskov Substitution Principle ) 概括:基类出现的地方,子类一定可以出现
  3. 依赖倒转原则(Depndece Inversion Principle) 概括:针对接口编程,依赖于抽象而不是具体
  4. 接口隔离原则(Interface Segregation Principle) 概括:使用多个隔离的接口,比使用单个接口好 (细分接口,降低耦合)
  5. 迪米特法则 (Demeter Principle) 概括:实体应当尽量少的与其他类发生互相作用,使得系统功能模块相对独立
  6. 开闭原则(Open Close Principle) 概括: 对扩展开放,对修改关闭

二、个人解读

概述

设计模式在代码层级中,是让你在某种业务场景刚开始设计时,能让未来的相关需求扩展极为方便的一个思想。 简单的说,在一开始设计好,扩展是很方便的,设计模式就是这个功劳者。 对于我们本来就懒的开发人员来说,这是求之不得的。

六大原则

而对于六大原则,简单过一下就行,不用刻意理解,如果你会了面向对象和设计模式的使用,自然就遵循了

三、今日主题

装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活`

场景

现在有一系列产品,需要计算他们的费用,而不同产品的可能有不同的费用,比如A产品有自己的利率费还有咨询费和服务费,B产品有自己的利率费还有服务费。

概述

将扩展行为抽成装饰者,如将利率,咨询费和服务费抽成行为;将各种产品抽象成被装饰者,如产品A 产品B;装饰者和被装饰者通过继承产品关系,通过组合处理行为。

相关代码

抽象元组件

代码语言:javascript复制
package top.huey.designpattern.decoration;

import java.math.BigDecimal;

/**
 * @author huey
 * @Description : 产品抽象类组件
 * @Date Created in 2018/7/22 10:40
 */
public abstract class Component {

    /**
     * @author huey
     * @Description : public 权限 子类修改
     * @Date Created in 2018/7/22 11:23
     */
    public String desc = "default Component";

    /**
     * @author huey
     * @Description : 默认描述
     * @Date Created in 2018/7/22 10:46
     */
    public void desc() {
        System.out.println(desc);
    }

    /**
     * @author huey
     * @Description : 产品计算自身利率金额
     * @Date Created in 2018/7/22 10:47
     */
    public abstract BigDecimal cost();
}

产品被装饰者

代码语言:javascript复制
package top.huey.designpattern.decoration;

import java.math.BigDecimal;

/**
 * @author huey
 * @Description : A产品
 * @Date Created in 2018/7/22 11:02
 */
public class AProduct extends Component{

    /**
     * @author huey
     * @Description : 产品计算自身利率金额
     * @Date Created in 2018/7/22 10:47
     */
    @Override
    public BigDecimal cost() {
        //此处写死,真正业务,可根据数据库 产品利率映射表来得
        return new BigDecimal(4.50);
    }
}


/**
 * @author huey
 * @Description : B产品
 * @Date Created in 2018/7/22 11:02
 */
public class BProduct extends Component{


    /**
     * @author huey
     * @Description : 产品计算自身利率金额
     * @Date Created in 2018/7/22 10:47
     */
    @Override
    public BigDecimal cost() {
        //此处写死,真正业务,可根据数据库 产品利率映射表来得
        return new BigDecimal(5.50);
    }
}

抽象装饰者组件

代码语言:javascript复制
package top.huey.designpattern.decoration;

/**
 * @author huey
 * @Description : 装饰着抽象类
 * 装饰着模式核心在于,装饰着和被装饰者有着共同的接口或者父类,继承来达到关联关系
 * 而行为扩展和装饰不是通过继承,而是通过组合。
 * 装饰着组合一个产品,做行为处理。
 * @Date Created in 2018/7/22 11:07
 */
public abstract class Decorator extends Component {

    /**
     * @author huey
     * @Description : 定义装饰的描述
     * @Date Created in 2018/7/22 11:16
     */
    public abstract void desc();
}

产品装饰者

代码语言:javascript复制
package top.huey.designpattern.decoration;

import java.math.BigDecimal;

/**
 * @author huey
 * @Description : A产品咨询费 装饰
 * @Date Created in 2018/7/22 11:20
 */
public class AProductConsult extends Decorator {

    private Component AProduct;

    public AProductConsult(Component AProduct) {
        this.AProduct = AProduct;
    }

    /**
     * @author huey
     * @Description : 定义装饰的描述
     * @Date Created in 2018/7/22 11:16
     */
    @Override
    public void desc() {
        System.out.println(this.desc   this.getClass().getName().toString());
    }

    /**
     * @author huey
     * @Description : A产品计算咨询费和自己利率金额和
     * @Date Created in 2018/7/22 10:47
     */
    @Override
    public BigDecimal cost() {
        return this.AProduct.cost().add(new BigDecimal(0.25));
    }
}


package top.huey.designpattern.decoration;

import java.math.BigDecimal;

/**
 * @author huey
 * @Description : A产品的服务费装饰
 * @Date Created in 2018/7/22 11:20
 */
public class AProductService extends Decorator {

    private Component AProduct;

    public AProductService(Component AProduct) {
        this.AProduct = AProduct;
    }

    /**
     * @author huey
     * @Description : 定义装饰的描述
     * @Date Created in 2018/7/22 11:16
     */
    @Override
    public void desc() {
        System.out.println(this.desc   this.getClass().getName().toString());
    }

    /**
     * @author huey
     * @Description : A产品计算服务费和自己利率金额和
     * @Date Created in 2018/7/22 10:47
     */
    @Override
    public BigDecimal cost() {
        return this.AProduct.cost().add(new BigDecimal(0.75));
    }
}

package top.huey.designpattern.decoration;

import java.math.BigDecimal;

/**
 * @author huey
 * @Description : B产品的服务费装饰
 * @Date Created in 2018/7/22 11:20
 */
public class BProductService extends Decorator {

    private Component BProduct;

    public BProductService(Component BProduct) {
        this.BProduct = BProduct;
    }

    /**
     * @author huey
     * @Description : 定义装饰的描述
     * @Date Created in 2018/7/22 11:16
     */
    @Override
    public void desc() {
        System.out.println(this.desc   this.getClass().getName().toString());
    }

    /**
     * @author huey
     * @Description : B产品计算服务费和自己利率金额和
     * @Date Created in 2018/7/22 10:47
     */
    @Override
    public BigDecimal cost() {
        return this.BProduct.cost().add(new BigDecimal(0.75));
    }
}

测试

代码语言:javascript复制
package top.huey.designpattern.decoration;

import org.junit.Test;

/**
 * @author huey
 * @Description : 装饰模式测试
 * @Date Created in 2018/7/22 11:31
 */
public class DecoratorTest {

    @Test
    public void test1() {
        Component aProduct = new AProduct();
        System.out.println("aProduct: "   aProduct.cost());
        Component bProduct = new BProduct();
        System.out.println("bProduct: "   bProduct.cost());
        AProductConsult aProductConsult = new AProductConsult(aProduct);
        AProductService aProductService = new AProductService(aProduct);
        System.out.println("aProductConsult"   aProductConsult.cost());
        System.out.println("aProductService"   aProductService.cost());
        BProductService bProductService = new BProductService(bProduct);
        System.out.println("bProductService"   bProductService.cost());
    }

}

四、读者须知

  1. 本系列文章内容会比较简陋,望有兴趣读者还是fork源码,调试一下。(如果你看过该书,一定可以加深印象)
  2. 联想下实际运用的哪些业务场景用到该模式,哪些中间件用到该模式,是否自己能在业务中使用。
  3. 即使你现在用不到某些设计模式,但是还是应该理解其原理的。
  4. 当时理解并不意味着自己已会,可以自己尝试练习,并幻想一种业务场景,画画类图,设计一下。

coding 时,做到了如何落实; writing时,做到了如何表达; sharing时,做到了如何传授; thinking时,做到了如何提升;

代码请参考码云:https://gitee.com/tjhuey/GodingGroup 设计模式相关概念请参考:http://naotu.baidu.com/file/5811bf42020e6a2d877b992cfca90d26

本期撰稿人:huey 本期审稿人:聆小小

本期责任编辑:兔子

0 人点赞