zoukankan      html  css  js  c++  java
  • 装饰者模式 详解

    定义

    Decorator是一种结构型设计模式,旨在促进代码复用;
    装饰者模式可以动态的给一个对象增加其他职责;就扩展功能来说,装饰者模式比生成子类更为灵活。

    角色

    • 抽象构件角色(AbstractComponent):定义对象的接口,可以给这些对象动态增加职责;
    • 抽象装饰角色(AbstractDecorator):维护一个指向Component实例的引用,并且定义了与Component一致的接口;
    • 具体构件角色(ConcreteComponent):定义具体的对象,Decorator可以给它增加额外的职责;
    • 具体装饰角色(ConcreteDecorator):具体的装饰对象,给内部持有的具体被装饰对象增加具体的职责;

    从网上找到的类图
    enter image description here

    适用场景

    • 当需要修改现有的系统,希望在系统中为对象添加额外的功* 能,而不需要大量修改它们的底层代码;
    • 包含了需要大量不同类型对象的功能;

    例子

    比如咖啡和调味品,包括很多种类的咖啡,调味品叶同样分为炼乳,巧克力,糖,牛奶等不同种类;其中咖啡和调味品都是需要单独收费的,这时候,咖啡作为基类,也就是装饰者模式中的抽象构件角色,不同种类的咖啡则继承自咖啡,其为具体构件角色,而在调味品中,调味品(同样继承咖啡,是咖啡的一部分)作为抽象装饰角色,不同的种类的调味品则作为具体具体装饰角色;


    实现代码

    • 代码一
    //衣服
    function WhiteClothes()
    {
    };
    WhiteClothes.prototype = {
        getPrice : function()
        {
            return 1000;
        }
    };
    
    function YellowClothes()
    {
    };
    YellowClothes.prototype = {
        getPrice : function()
        {
            return 800;
        }
    };
    
    //搭配
    function Hat(clothes)
    {
        this.clothes = clothes;
    };
    Hat.prototype =
    {
        getPrice : function()
        {
            return this.clothes.getPrice() + 100;
        }
    };
    
    function Tie(clothes)
    {
        this.clothes = clothes;
    };
    Tie.prototype =
    {
        getPrice : function()
        {
            return this.clothes.getPrice() + 120;
        }
    };
    
    
    var clothes = new WhiteClothes();
    //白衣服搭配帽子
    var hat = new Hat(clothes);
    console.log(hat.getPrice());
    //白衣服搭配领带
    var tie = new Tie(clothes);
    console.log(tie.getPrice());
    //白衣服搭配帽子和领带
    var hattie = new Tie(hat);
    console.log(hattie.getPrice());
    
    

    实现结果为

    这里写图片描述

    • 代码二
    //抽象组件者
    var MacbookPro = function () {
    
    };
    
    //具体组件者
    MacbookPro.prototype = {
        addEngraving : function () {
        },
        addParallels : function () {
        },
        add4GBRam : function () {
        },
        add8GBRam : function () {
        },
        addCase : function () {
        },
        getPrice : function () {
            return 900.00;
        }
    };
    
    //继承函数
    function extend( subClass, superClass ){
        var F = function(){};
        F.prototype = superClass.prototype;
        subClass.prototype = new F();
        subClass.prototype.constructor = subClass;
    
        // 此处指向superClass的prototype 比直接保存superClass使用更为方便
        subClass.superclass = superClass.prototype;
        if( superClass.prototype.constructor === Object.prototype.constructor ){
            superClass.prototype.constructor = superClass;
        }
    }
    
    //中间装饰者
    var MacbookDecorator = function (macbook) {
        this.macbook = macbook;
    };
    
    MacbookDecorator.prototype = {
        addEngraving : function () {
            return this.macbook.addEngraving();
        },
        addParallels : function () {
            return this.macbook.addParallels();
        },
        add4GBRam : function () {
            return this.macbook.add4GBRam();
        },
        add8GBRam : function () {
            return this.macbook.add8GBRam();
        },
        addCase : function () {
            return this.macbook.addCase();
        },
        getPrice : function () {
            return 900.00;
        }
    };
    
    //具体装饰者
    var CaseDecorator = function (macbook) {
        CaseDecorator.superclass.constructor.call(this,macbook);
    };
    
    //扩展超类
    extend(CaseDecorator, MacbookDecorator);
    
    CaseDecorator.prototype.addCase = function () {
        return this.macbook.addCase() + "Adding case to macbook";
    };
    
    CaseDecorator.prototype.getPrice = function () {
        return this.macbook.getPrice() + 45.00;
    };
    
    var pro = new MacbookPro();
    console.log(pro.getPrice());
    
    pro = new CaseDecorator(pro)
    console.log(pro.getPrice());
    

    运行结果为:


    优缺点

    注意的是,如果管理不当,它会极大的复杂化应用程序结构,因为它向我们的命名空间引入了很多小型但类似的对象。

  • 相关阅读:
    翘边阴影
    原生js实现 拖拽事件
    js实现计算器
    js实现选项卡
    js随机生成座号
    1.记住密码 提示框
    媒体查询
    高性能JavaScript 读书笔记
    調用WEB services
    Dragon Quest VIII 流程攻略(繁体中文完结版)
  • 原文地址:https://www.cnblogs.com/George1994/p/6037701.html
Copyright © 2011-2022 走看看