精华内容
下载资源
问答
  • 装饰者模式

    2020-03-25 17:26:09
    装饰者模式优点 装饰者模式是继承的有力补充,且比继承灵活,可以砸不改变原有对象的情况下,动态地给一个对象扩展功能,即插即用 使用不同的装饰类及这些装饰类的排列组合,可以实现不同的效果 装饰者模式完全...

    装饰者模式优点

    • 装饰者模式是继承的有力补充,且比继承灵活,可以砸不改变原有对象的情况下,动态地给一个对象扩展功能,即插即用
    • 使用不同的装饰类及这些装饰类的排列组合,可以实现不同的效果
    • 装饰者模式完全符合开闭原则

    装饰者模式缺点

    • 会出现更多的代码,更多的类,增加程序的复杂性
    • 动态装饰时,多层装饰会更复杂

    我们用装饰者模式来实现生活场景

    创建一个煎饼类抽象类Battercake

    
    /**
     * @Author Lxq
     * @Date 2020/3/25 16:01
     * @Version 1.0
     * 煎饼类
     */
    public abstract class Battercake {
    
        protected abstract String getMsg();
        protected abstract int getPrice();
    
    }
    

     然后创建一个基本的煎饼类(基础套餐)BaseBattercake

    /**
     * @Author Lxq
     * @Date 2020/3/25 16:26
     * @Version 1.0
     * 基础套餐(基本煎饼类)
     */
    public class BaseBattercake extends Battercake {
    
        @Override
        protected String getMsg() {
            return "煎饼";
        }
    
        @Override
        protected int getPrice() {
            return 5;
        }
    }
    

    创建一个扩展套餐的抽象装饰类BattercakeDecorator

    /**
     * @Author Lxq
     * @Date 2020/3/25 16:30
     * @Version 1.0
     * 抽象装饰类
     */
    public abstract class BattercakeDecorator extends Battercake {
    
        //静态代理,委派
        Battercake battercake;
    
    
        public BattercakeDecorator(Battercake battercake) {
            this.battercake = battercake;
        }
    
        protected abstract void doSomething();
    
        @Override
        protected String getMsg() {
            return this.battercake.getMsg();
        }
    
        @Override
        protected int getPrice() {
            return this.battercake.getPrice();
        }
    }
    

    接下里就是鸡蛋的装饰类EggDecorator

    /**
     * @Author Lxq
     * @Date 2020/3/25 16:35
     * @Version 1.0
     * 鸡蛋装饰类
     */
    public class EggDecorator extends BattercakeDecorator{
    
        public EggDecorator(Battercake battercake) {
            super(battercake);
        }
    
        @Override
        protected void doSomething() {
    
        }
    
        @Override
        protected String getMsg() {
            return super.getMsg() + "1个鸡蛋";
        }
    
        @Override
        protected int getPrice() {
            return super.getPrice() + 1;
        }
    }
    

    最后创建香肠的装饰类

    
    /**
     * @Author Lxq
     * @Date 2020/3/25 16:37
     * @Version 1.0
     * 香肠的装饰类
     */
    public class SausageDecorator extends BattercakeDecorator{
    
        public SausageDecorator(Battercake battercake) {
            super(battercake);
        }
    
        @Override
        protected void doSomething() {
    
        }
    
        @Override
        protected String getMsg() {
            return super.getMsg() + "1根香肠";
        }
    
        @Override
        protected int getPrice() {
            return super.getPrice() + 2;
        }
    }
    

    编写客户端代码测试

    public class Test {
        public static void main(String[] args) {
            Battercake battercake;
            // 买一个煎饼不加东西
            battercake = new BaseBattercake();
            // 煎饼太小了,帮我加个鸡蛋
            battercake = new EggDecorator(battercake);
            // 妈耶一个鸡蛋这小,再来一个
            battercake = new EggDecorator(battercake);
            // 肚子太饿了,加一个香肠
            battercake = new SausageDecorator(battercake);
    
            System.out.println(battercake.getMsg() + ",总价" + battercake.getPrice());
        }
    }
    

    煎饼1个鸡蛋1个鸡蛋1根香肠,总价9

    展开全文
  • 装饰者模式优点: 装饰者模式应用: 装饰者实例: 上述代码 GitHub 地址:https://github.com/baicun/designPatterns 装饰者模式: 装饰者模式就像打包一个快递,打包的物体不会变,但会用到不同的包装,最后...

    目录

    装饰者模式:

    装饰者模式优点:

    装饰者模式应用:

    装饰者实例:

    上述代码 GitHub 地址:https://github.com/baicun/designPatterns


    装饰者模式:

    装饰者模式就像打包一个快递,打包的物体不会变,但会用到不同的包装,最后发货。像这些不同的包装,动态的附加到对象上。

    装饰者模式优点:

    装饰模式与继承关系的目的都是要扩展对象的功能,继承关系可能会因为组合太多出现类爆炸,所以装饰比继承更有弹性。

    装饰者模式应用:

    Java IO流中FilterInputStream的设计。

    装饰者实例:

    类图:

    以咖啡店作为样例:不同顾客喜欢不同口味的咖啡,以此我们创建一个基类(Drink);首先根据不同口味分为无糖(Decaf)咖啡、浓咖啡(Espresso),根据不同的调味品我们分为牛奶(Milk)、豆浆(Soy),不同客人的口味可能会加多份牛奶或是多份豆浆,或是混合起来,需求多变,此时运用装饰者模式灵活的将调味品装饰在咖啡这个主体上。

    咖啡基类:

    public abstract class Drink {
    
        public String description="";
        private float price=0f;
    
        // cost方法是给装饰者提供拓展方法
        public abstract float cost();
        public void setDescription(String description)
        {
            this.description=description;
        }
    
        public String getDescription()
        {
            return description+"-"+this.getPrice();
        }
    
        public float getPrice()
        {
            return price;
        }
        public void setPrice(float price)
        {
            this.price=price;
        }
    }

    咖啡成品-无糖

    public class Decaf extends Coffee{
        public Decaf(){
            super.setDescription("Decaf");
            super.setPrice(3.0f);
        }
    }

    咖啡调料-牛奶

    public class Milk extends Decorator{
        public Milk(Drink drink) {
            super(drink);
            super.setDescription("Milk");
            super.setPrice(2.0f);
        }
    }

    需要注意的是,装饰者构造方法要传入主体对象。

    测试类:

    public class MainTest {
        public static void main(String[] args){
            Drink drink;
            drink = new Decaf();
            System.out.println("描述 = [" + drink.getDescription() + "]");
    
            drink = new Espresso();
            drink = new Milk(drink);
            drink = new Soy(drink);
            drink = new Soy(drink);
            System.out.println("价格 = [" + drink.cost() + "]");
            System.out.println("描述 = [" + drink.getDescription() + "]");
    
        }
    }

     

    上述代码 GitHub 地址:https://github.com/baicun/designPatterns

    展开全文
  • 目录装饰者模式代码示例 装饰者模式 装饰者模式(Decorator Pattern)是指在不改变原有对象的基础上,将功能附加到对象上,实现对原有对象功能的...装饰者模式优点: 1、比继承更加灵活,可以在不改变原有对象的基...

    装饰者模式

    • 装饰者模式(Decorator Pattern)是指在不改变原有对象的基础上,将功能附加到对象上,实现对原有对象功能的扩展,比继承更加灵活。装饰者模式属于结构型设计模式。
    • 装饰者模式的适用场景:
      1、用于扩展一个类的功能或给一个类添加附加功能
      2、动态的给一个类添加功能,同时这些功能可以动态的取消
    • 装饰者模式优点:
      1、比继承更加灵活,可以在不改变原有对象的基础上,动态的给对象添加功能
      2、通过不同的装饰类,实现对不同功能的组合,以实现不同的效果
      3、完全遵守开闭原则
    • 装饰者模式缺点:
      1、增加了代码和更多的类,增加了代码的复杂性
      2、动态装饰或者多层装饰时,使得装饰更加复杂

    代码示例

    • 以我们日常生活的一个小例子作为代码示例,比如我们经常会买煎饼作为早餐,买煎饼的时候,会加鸡蛋或者火腿等,加不同的材料会有不同的价格,那么首先定义一个煎饼类:
    public abstract class Battercake {
        public abstract String getMessage();
        public abstract int getPrice();
    }
    
    
    • 首先定义一个什么都不加的煎饼类:
    public class BaseBattercake extends Battercake {
        @Override
        public String getMessage() {
            return "一个煎饼";
        }
    
        @Override
        public int getPrice() {
            return 6;
        }
    }
    
    
    • 创建一个用于选择不同套餐的装饰者类:
    public class BattercakeDecorator extends Battercake {
        private Battercake battercake;
    
        public BattercakeDecorator(Battercake battercake) {
            this.battercake = battercake;
        }
    
        @Override
        public String getMessage() {
            return this.battercake.getMessage();
        }
    
        @Override
        public int getPrice() {
            return this.battercake.getPrice();
        }
    }
    
    • 创建一个加鸡蛋的装饰者类:
    public class EggDecorator extends BattercakeDecorator{
    
        public EggDecorator(Battercake battercake) {
            super(battercake);
        }
    
        @Override
        public String getMessage() {
            return super.getMessage() + "加一个鸡蛋";
        }
    
        @Override
        public int getPrice() {
            return super.getPrice() + 1;
        }
    }
    
    • 创建一个加香肠的装饰者类:
    public class SausageDecorator extends BattercakeDecorator {
        public SausageDecorator(Battercake battercake) {
            super(battercake);
        }
    
        @Override
        public String getMessage() {
            return super.getMessage() + "加一根香肠";
        }
    
        @Override
        public int getPrice() {
            return super.getPrice() + 2;
        }
    }
    
    • 写一个测试类:
    public class test {
        public static void main(String[] args) {
            //买一个煎饼
            Battercake battercake = new BaseBattercake();
            //加个鸡蛋
            battercake = new EggDecorator(battercake);
            //加个香肠
            battercake = new SausageDecorator(battercake);
            //再加个鸡蛋
            battercake = new EggDecorator(battercake);
    
            System.out.println("您的煎饼:" + battercake.getMessage() +
                    ",价格是:" + battercake.getPrice());
        }
    }
    
    • 看下结果:
      在这里插入图片描述
    • UML类图如下所示:
      在这里插入图片描述
    展开全文
  • 装饰者模式优点 IV . 装饰者模式与继承对比 V . 装饰者模式相关设计模式 VI . 装饰者模式四个相关类 VII . 装饰者模式实体装饰者类运行机制 VIII . 装饰者模式定义使用流程 ( 重点 ) IX . 装饰者模式 案例



    I . 装饰者模式概念



    装饰者模式概念 :


    ① 设计模式类型 : 结构性 ;

    ② 概念 : 不改变原有类的对象 , 动态地将额外的功能附加到该对象上 ;

    ③ 扩展对象功能 : 这种功能扩展方式比类继承更加灵活 ;

    ④ 装饰者模式 : 移除类中的被装饰功能 , 将被装饰类简化 , 区分类的核心职责 和 装饰功能 ;



    II . 装饰者模式适用场景



    装饰者模式适用场景 :


    ① 功能扩展 : 为一个类扩展功能 , 为其添加额外的职责 ; ( 强调扩展 )

    ② 动态添加撤销功能 : 为一个对象动态添加额外功能 , 同时这些被添加的功能还能被动态撤销 ; ( 强调动态 )



    III . 装饰者模式优缺点



    装饰者模式优点 :


    ① 扩展灵活 : 使用装饰者模式 , 比继承更加灵活 ; 使用装饰者模式扩展类功能 , 不会改变原来的类 ;

    ② 排列组合 : 对装饰类进行各种排列组合 , 可实现不同的扩展功能 ;

    ③ 开闭原则 : 装饰者模式符合开闭原则 , 被装饰的类 , 和装饰类相互独立 , 互不干扰 ;


    装饰者模式缺点 :


    ① 程序复杂 : 需要编写更多的代码 , 生成更多的类 , 程序的复杂性增加了 ;

    ② 动态 / 多层 装饰 : 动态 / 多层 装饰一个类时 , 程序更复杂 ;



    IV . 装饰者模式与继承对比



    继承与装饰者模式对比 :


    ① 继承复杂 : 使用继承扩展功能 , 需要生成很多子类 , 系统复杂性增加 ;

    ② 继承静态 : 继承在编译时就要确定扩展的功能 , 是静态的 ;

    ③ 装饰者模式动态扩展 : 装饰者模式可以动态扩展功能 , 可以在代码运行时扩展功能 ;



    V . 装饰者模式相关设计模式



    1 . 装饰者模式与代理模式 :


    ① 注重点 : 装饰者模式注重动态扩展功能 ; 代理模式注重对对象访问的控制 , 代理类对用户隐藏具体细节 ;

    ② 实例对象的使用 : 装饰者模式将原始对象作为参数传递给装饰者类构造器 ; 代理模式中在代理类中创建实例对象 ;


    2 . 装饰者模式与适配器模式 : 二者都是包装模式 ;


    ① 装饰者模式 : 装饰者模式中 , 装饰者和被装饰这实现相同的接口 , 或装饰者是被装饰者的子类 ;

    ② 适配器模式 : 适配器模式中 , 适配器和被适配的类有不同的接口 , 可能有部分接口重合 ;



    VI . 装饰者模式四个相关类



    装饰者模式四个相关类 :


    抽象的 被装饰者类 : 这是核心 , 后面的三个类都需要继承该类 ;

    ② 实体的被装饰者类 : 定义装饰者模式时 , 用不到 , 在客户端被用户调用时 , 才初始化 ;

    ③ 抽象的装饰者类 : 所有装饰者类的父类 , 需要继承抽象的被装饰者类 ; ( 该类可选配 , 不是必须 )

    ④ 实体的装饰者类 : 继承 抽象的装饰者类 , 在该类中维护一个 抽象装饰者类对象 , 通过构造函数传入实体的被装饰者类 , 其实现的 抽象的装饰者类 方法中 , 需要调用传入的实体对象的对应方法 , 然后加入额外的操作 ;



    VII . 装饰者模式实体装饰者类运行机制



    实体的装饰者类运行机制 :


    ① 核心 : 核心是 抽象的 被装饰者类 类型 ,

    ② 装饰者类型 : 实体的装饰者类是 抽象的 被装饰者类 类型的 ,

    ③ 装饰者中维护的变量类型 : 其中维护的实例成员变量也是 抽象的 被装饰者类 类型的 ,

    ④ 装饰者模式运行 : 装饰者模式使用时 , 先创建一个 抽象的 被装饰者类 实例对象 , 创建一个装饰者对象 , 通过构造函数将上面的实例对象传入 , 整个装饰者模式就是为该实例对象进行扩展的 ;

    ⑤ 装饰可循环嵌套 : 实体的被装饰类类型是 抽象的 被装饰者类 类型的 , 其被装饰后 , 还是 抽象的 被装饰者类 类型的 , 然后还可以再次装饰 , 实体的被装饰类的动态功能的扩展 , 可以被无限装饰扩展 ;



    VIII . 装饰者模式定义使用流程 ( 重点 )



    1 . 定义抽象被装饰者 : 定义 抽象的 被装饰者类 , 将其要扩展的方法定义成抽象方法 ;


    2 . 定义 ( 抽象的 ) 装饰者类 :


    ① 继承 抽象的 被装饰者类 : 装饰者类 继承 抽象的 被装饰者类 ;

    ② 维护 抽象的 被装饰者类 成员 : 在该类中维护一个 抽象的 被装饰者类 对象 , 该对象通过构造函数传入 ;

    ③ 实现抽象方法委托 : 装饰者类中的抽象方法 , 需要委托给类中维护的 抽象的 被装饰者类 对象 , 在实现的该抽象方法中 , 调用上面对象的对应方法 , 然后加上要扩展的代码 , 这些扩展的代码 , 就是装饰者模式位该对象动态扩展的功能 ;


    3 . 定义实体对象 : 该对象是 抽象的 被装饰者类 类型的 , 是具体的实体功能 , 要实现实际的大块代码逻辑 , 所有的操作 , 装饰 , 都基于该实体对象类 ;

    上面的装饰者类 只关心被装饰的方法 , 不定义其它内容 ;


    4 . 使用装饰者模式 :


    ① 创建 抽象的 被装饰者类 实体对象 ;

    ② 装饰实体对象类 : 创建 抽象的 被装饰者类 类型的装饰者类 , 在构造函数中 , 传入 ① 中创建的 抽象的 被装饰者类 类型的 实体对象 ;

    ③ 再次装饰实体对象类 : 再次创建 抽象的 被装饰者类 类型的装饰者类 , 在构造函数中 , 传入 ② 中创建的 抽象的 被装饰者类 类型的 装饰者实体对象 , 这样就实现了二次装饰 ;


    使用的对象类型是 抽象的 被装饰者类 , 被装饰的对象 , 传入装饰者类 , 相当于包装了一层 , 其对象类型还是 抽象的 被装饰者类 , 这个包装装饰可以循环嵌套 ;



    IX . 装饰者模式 案例



    1 . 案例需求 :


    ① 实体类对象 : 刚入学的学生 , 默认学习大学公共课 ,

    ② 装饰类对象 : 如果是计算机专业的学生 , 还要继续学习计算机专业课程 ,

    ③ 装饰类对象 : 如果是音乐专业的学生 , 需要继续学习音乐专业课程 ,

    ④ 二次装饰类对象 : 如果是先学习计算机 , 然后专修音乐 , 那么需要先学习计算机专业课程 , 然后学习音乐专业课程 ;


    2 . 抽象的 被装饰者类 : 抽象的学生类 , 后面的计算机专业学生装饰者 , 音乐专业学生装饰者都继承该类 ;

    package kim.hsl.design.decorator;
    
    /**
     * 装饰者
     * 抽象的装饰者
     * 该类也继承 被装饰者 的抽象类
     */
    public abstract class AbstractDecorator extends AbstractStudent {
    
        //声明抽象的被装饰者, 通过构造器将其类型 ( 或子类类型 ) 对象传入 , 注入实体类
        private AbstractStudent abstractStudent;
    
        public AbstractDecorator(AbstractStudent abstractStudent) {
            this.abstractStudent = abstractStudent;
        }
    
        /*
           调用实现的两个 抽象装饰者 方法
           实际上委托给了注入的 抽象装饰者 类型的对象执行的
           抽象装饰者 类型的对象是其子类对象
         */
    
        @Override
        protected String studyCourses() {
            return this.abstractStudent.studyCourses();
        }
    }
    

    3 . 刚入学的学生类 : 这是最普通的实体 , 是被装饰的实体类 , 一切装饰都是围绕着该实体来的 ;

    package kim.hsl.design.decorator;
    
    /**
     * 被装饰对象
     * 确定的实体类
     */
    public class Student extends AbstractStudent {
    
        @Override
        protected String studyCourses() {
            return "学习大学公共课";
        }
    }
    

    4 . 抽象的被装饰者类 : 该类也是 抽象的被装饰者 类 AbstractStudent 的子类 , 该类中维护了 AbstractStudent 类型的成员变量 , 通过构造函数初始化 ; 其 studyCourses 方法需要委托给 abstractStudent 成员变量的 abstractStudent 方法 ;

    package kim.hsl.design.decorator;
    
    /**
     * 装饰者
     * 抽象的装饰者
     * 该类也继承 被装饰者 的抽象类
     */
    public abstract class AbstractDecorator extends AbstractStudent {
    
        //声明抽象的被装饰者, 通过构造器将其类型 ( 或子类类型 ) 对象传入 , 注入实体类
        private AbstractStudent abstractStudent;
    
        public AbstractDecorator(AbstractStudent abstractStudent) {
            this.abstractStudent = abstractStudent;
        }
    
        /*
           调用实现的两个 抽象装饰者 方法
           实际上委托给了注入的 抽象装饰者 类型的对象执行的
           抽象装饰者 类型的对象是其子类对象
         */
    
        @Override
        protected String studyCourses() {
            return this.abstractStudent.studyCourses();
        }
    }
    

    5 . 计算机专业学生装饰者类 : 传入 AbstractStudent 成员变量 , studyCourses 方法中 , 在学习公共课基础上 ( 委托成员变量 ) , 还学习 计算机专业课程 ;

    package kim.hsl.design.decorator;
    
    /**
     * 实体装饰者类
     * 必须实现其带参数的构造器
     */
    public class ComputerStudentDecorator extends AbstractDecorator {
    
        public ComputerStudentDecorator(AbstractStudent abstractStudent) {
            super(abstractStudent);
        }
    
        @Override
        protected String studyCourses() {
            return super.studyCourses() + " , 学习计算机专业课程";
        }
    }
    

    6 . 音乐专业学生装饰者类 :

    package kim.hsl.design.decorator;
    
    public class MusicStudentDecorator extends AbstractDecorator {
    
        public MusicStudentDecorator(AbstractStudent abstractStudent) {
            super(abstractStudent);
        }
    
        @Override
        protected String studyCourses() {
            return super.studyCourses() + " , 学习音乐专业课程";
        }
    }
    

    7 . 测试装饰者模式 : 其中测试了没有装饰的实体类 , 将其装饰成计算机专业学生 , 将其装饰成音乐专业学生 , 将其装饰成计算机转音乐专业的学生 ;

    package kim.hsl.design.decorator;
    
    public class Main {
    
        public static void main(String[] args) {
    
            //刚入学的学生
    	    Student student = new Student();
    	    System.out.println(student.studyCourses());
    
    	    //大二学习计算机专业课程
            AbstractStudent computerStudent = new ComputerStudentDecorator(student);
            System.out.println(computerStudent.studyCourses());
    
            //大二学习音乐专业课程
            AbstractStudent musicStudent = new MusicStudentDecorator(student);
            System.out.println(musicStudent.studyCourses());
    
            //先学计算机 , 专修音乐的学生
            AbstractStudent computerMusicStudent = new ComputerStudentDecorator(computerStudent);
            System.out.println(computerMusicStudent.studyCourses());
    
        }
    }
    
    
    展开全文
  • 目录一、装饰者模式的定义与类型二、装饰者模式的适用场景三、装饰者模式优点四、装饰者模式的缺点五、装饰者模式相关的设计模式六、普通示例:七、普通示例演进,使用装饰者模式示例: 一、装饰者模式的定义与...
  • 2.装饰者模式优点 有效地把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。 3.装饰者模式的特点 1.装饰者与被装饰对象有相同的超类型。 2.可以用一个或多个装饰者包装一个对象。 3.既然...
  • java装饰者模式

    2020-07-28 18:22:36
    装饰者模式类结构 Component:被装饰对象的抽象接口,规范(定义)了需要装饰的操作 ConcreteComponent:被装饰的具体对象 Decorator:装饰者抽象,统一管理各种装饰者,持有Component,并且继承Component ...

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 363
精华内容 145
关键字:

装饰者模式优点