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

    模式导读:

        给你一个没装修的房子,让你利用自己的艺术细菌去想象如何去让自己的房子更加漂亮,更加完美。这就需要我们慢慢去思考了...通过动态的给一个对象增加新的功能,使无需通过继承的方式增加子类既能够扩展对象功能,使用对象的关联关系代替继承关系,更加灵活,同时类型体系的快速膨胀。至于使用继承关系实现为什么膨胀,看下面这张图你就清楚了。

    很明显,如果对象的功能开始复杂起来时,我们需要重新定义一个新的对象来实现,这就增加了更多地子类,所以膨胀了。

    参考类图:

    1.Component抽象构件角色:使真实对象和装饰对象有相同的接口,这样,客户端对象就能够以真实对象相同的方式同装饰对象交互。
    2.ConcretComponent具体构件角色(真实对象):如io流中的FileInputStream,FileOutputStream。
    3.Decorator装饰角色:持有一个抽象构件的引用,装饰对象接收所有的客户端的请求,并把这些请求转发给真实的对象,这样就能够在真实对象调用前后增加新的功能。
    4.ConcretDecorator具体装饰角色:负责给构件对象增加新的责任。
    代码实现:

    1.抽象构件类

    1 package com.etc;
    2 //抽象构件角色
    3 public interface AbstractCar {
    4      void move();
    5 }

    2.具体构件类

     1 package com.etc;
     2 //具体构件角色
     3 public class Car implements AbstractCar{
     4 
     5     @Override
     6     public void move() {
     7         System.out.println("**正常由人操控陆地行驶!**");
     8     }
     9 
    10 }

    3.装饰者角色类

     1 package com.etc;
     2 //装饰角色,将传入的不同请求转发给真实对象
     3 public class Decorator implements AbstractCar{
     4     private AbstractCar car;
     5     //构造器,用于接收具体的装饰子对象
     6     public Decorator(AbstractCar car) {
     7         super();
     8         this.car = car;
     9     }
    10     @Override
    11     public void move() {
    12         car.move();
    13     }
    14 
    15 }

    4.特征类

     1 //将共同的特征抽取出来  ->swim,fly,ai
     2 public class Feature {
     3 
     4     // 私有化构造器
     5     private Feature() {
     6 
     7     }
     8 
     9     // 可以潜水
    10     public static void swim() {
    11         System.out.println("具备潜水功能");
    12     }
    13 
    14     // 可以飞
    15     public static void fly() {
    16         System.out.println("具备飞行功能");
    17     }
    18 
    19     // 可以人工智能
    20     public static void ai() {
    21         System.out.println("具备人工智能");
    22     }
    23 }

    5.具体装饰角色类

     1 public class SwimCar extends Decorator {
     2 
     3     public SwimCar(AbstractCar car) {
     4         super(car);
     5     }
     6 
     7     // 重写父类的方法,给车增加swim()的功能
     8     public void move() {
     9         super.move();
    10         Feature.swim();
    11     }
    12 }
     1 public class SwimFlyCar extends Decorator {
     2 
     3     public SwimFlyCar(AbstractCar car) {
     4         super(car);
     5     }
     6 
     7     // 重写父类的方法,给车增加fly(),swim()的功能
     8     public void move() {
     9         super.move();
    10         Feature.fly();
    11         Feature.swim();
    12     }
    13 }
     1 //具体的装饰角色
     2 public class FlyCar extends Decorator {
     3 
     4     public FlyCar(AbstractCar car) {
     5         super(car);
     6     }
     7 
     8     // 重写父类的方法,给车增加fly()的功能
     9     public void move() {
    10         super.move();
    11         Feature.fly();
    12     }
    13 }
     1 public class AICar extends Decorator {
     2 
     3     public AICar(AbstractCar car) {
     4         super(car);
     5     }
     6 
     7     // 重写父类的方法,给车增加AI()的功能
     8     public void move() {
     9         super.move();
    10         Feature.ai();
    11     }
    12 }

    6.客户端类

     1 package com.etc;
     2 //根据情景需要给车增加不同的功能
     3 public class Client {
     4 
     5     public static void main(String[] args) {
     6         //让车增加可以飞的功能
     7         Car car=new Car();
     8         FlyCar flyCar=new FlyCar(car);
     9         flyCar.move();
    10         //让车增加可以潜水的功能
    11         SwimCar swimCar=new SwimCar(car);
    12         swimCar.move();
    13         //让车增加可以潜水,飞的功能
    14         SwimFlyCar sfCar=new SwimFlyCar(car);
    15         sfCar.move();
    16     }
    17 
    18 }

    效果截图:

    装饰模式的优缺点:

    优点:

    装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

    缺点:

    多层装饰比较复杂。

    适用场景:

    1、扩展一个类的功能。
    2、动态增加功能,动态撤销。

  • 相关阅读:
    RPC调用框架比较分析--转载
    hbase快速入门
    美国诚实签经验——着装,戒指,手表装土豪,医生预约单,流水、房产和工作证明
    美国诚实签经验——英语演练回答,回答中说明目的,需要的时间和费用
    美国诚实签经验——医院预约单和医院资料,孕中保险是加分项
    东京一日游
    cassandra删除所有数据,重置为初始状态——删除<data dir>/data/* <data dir>/commitlog/* <data dir>/saved_caches/* 重启cassandra即可
    echo 到 stderr
    bash编程 将一个目录里所有文件存为一个array 并分割为三等分——利用bash array切片
    linkerd——针对java的为微服务提供可靠性的proxy,服务发现重试LB等
  • 原文地址:https://www.cnblogs.com/weekstart/p/decarator.html
Copyright © 2011-2022 走看看