zoukankan      html  css  js  c++  java
  • 设计模式之装饰者模式

    概要

    动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。

    装饰者对象的角色

    Component(抽象构件):

    它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。

    ConcreteComponent(被装饰者):

    它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。

    Decorator(抽象装饰类):

    它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。

    ConcreteDecorator(具体装饰类):

    它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。

    由于具体构件类和装饰类都实现了相同的抽象构件接口,因此装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。

    上面是装饰者模式角色说明。

    实际应用场景

    在双11 就要来临之际,电商为了促销,想出了各种手段,比如打折,发红包等等,这里就可以用到装饰者模式。

    购买商品的款项为 被装饰者对象。

    红包可以认为是装饰器,打折也是。

    下面就用代码说明上面说的各种角色。

    1.抽象构件

    import java.math.BigDecimal;
    
    public interface Component {
    
        BigDecimal getCount();
    }

    2.被装饰者

    import java.math.BigDecimal;
    
    public class FactPrice implements Component {
        @Override
        public BigDecimal getCount() {
            return new BigDecimal("100");
        }
    }

    这里是实际的价格。

    3.抽象装饰器

    public class Decorator implements Component {
    
        private Component component;
    
        @Override
        public BigDecimal getCount() {
            return this.component.getCount();
        }
    
        public void setDecorator(Component decorator) {
            this.component=decorator;
        }
    }

    4.红包

    public class RedDecorator extends Decorator {
    
        @Override
        public BigDecimal getCount() {
            return   super.getCount().subtract(new BigDecimal("5"));
        }
    }

    5.折扣

    public class DiscountDecortor extends  Decorator {
    
        @Override
        public BigDecimal getCount() {
            return  super.getCount().multiply(new BigDecimal("0.8"));
        }
    }

    6.调用者

    public class Invoker {
    
        public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
            Component user=new FactPrice();
    
            List<Decorator> decorators=new ArrayList<>();
    
            decorators.add(new RedDecorator());
            decorators.add(new DiscountDecortor());
            for(Decorator decorator :decorators){
                decorator.setDecorator(user);
                user=decorator;
            }
    
            System.err.println(user.getCount()) ;
        }
    }

    这里我们先 得到100块,减掉5块钱红包,在在这个基础上打8折。结果是76块。

    也可以调整优惠顺序,可以 先打八折,在减掉5块。结果需要75块。

    在实际的应用中,这些装饰者,可以通过调整装饰者类顺序或者根据不同的场景使用不同的装饰者,实现灵活的打折策略。

  • 相关阅读:
    Katta:基于Lucene可伸缩分布式实时搜索方案
    cnprog
    Eclipse开发struts完全指南(二)安装与配置
    MYSQL 数据库导入导出命令
    ubuntuapache下隐藏thinkphp入口文件index.php
    PHP过滤指定字符串,过滤危险字符
    // 关闭调试模式  define('APP_DEBUG', false);
    Javascript读书笔记(1):从零开始
    Facebook messages实现解读
    《推荐系统实践》
  • 原文地址:https://www.cnblogs.com/yg_zhang/p/11816916.html
Copyright © 2011-2022 走看看