4

设计模式之(7)——装饰设计模式 - 一只烤鸭朝北走

 2 years ago
source link: https://www.cnblogs.com/wha6239/p/16646861.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

设计模式之(7)——装饰设计模式

  定义:装饰设计模式允许向一个现有的对象添加功能,而不改变其结构(这就很符合程序设计的“开闭原则”),重点突出类功能的增强,属于结构型创建模式,这种模式创建了一个装饰类,用来包装原有类,保持类方法签名完整的情况下,提供了额外的功能。

  意图:动态地给一个对象增加一些额外的职责,装饰是比子类更为灵活和优秀的一种方案;

  主要解决:通常扩展一个类我们通常使用继承实现,由于继承为类引入特征,通常随着功能的扩展,子类会很膨胀,容易造成类爆炸;装饰设计模式是一种使用组合替代继承的最佳实现,《effective java》中也建议“组合优先于继承”,面向对象编程有封装、继承和多态三大特征,其中封装和继承却有一点矛盾,继承意味着子类依赖了父类的实现,一旦父类中改变了规则,会对子类造成影响,这是打破封装的一种表现,而组合就是巧用封装来实现继承功能的代码复用;

  何时使用:在不想增加很多子类的情况下扩展类的功能;

  设计模式结构图:

  

1139198-20220901151624939-186633392.png

  模式角色分析:

  1、抽象构件角色(Component):定义一个抽象接口,用来规范被装饰类的行为;

  2、具体构件角色(ConcreteComponent):需要被装饰的目标对象;

  3、抽象装饰角色(decorator):持有一个具体构件对象的实例,并定义一个与抽象构建接口一致的接口;

  4、具体装饰角色(ConcreteDecorator):具体的装饰类,负责给被装饰者扩展功能;

  优点:

  1、装饰和继承都能达到扩展类功能的目的,但是装饰模式更加灵活;

  2、装饰设计模式有很好的可扩展性;

  3、通过使用不同的具体装饰类,以及这些类的排列组合,可以实现多重装饰;

  缺点:

  装饰设计或是会导致程序设计中出现许多小对象,如果过度使用会使程序变得更加复杂;

  UML类图:

  

1139198-20220901190559346-479590519.png

  测试代码:

package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: Shape  
 * @Description:  抽象构件角色(Component),用来约束被装饰对象的行为
 * @author wwh 
 * @date 2022-9-1 16:11:29
 */
public interface Shape {

    /**
     * 
     * @Title: draw 
     * @Description:
     */
    public void draw();
}
package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: Circle  
 * @Description:  具体构件角色(ConcreteComponent),被装饰的对象
 * @author wwh 
 * @date 2022-9-1 16:14:50
 */
public class Circle implements Shape {

    @Override
    public void draw() {
        System.err.println("Shape: Circle.");
    }

}
package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: Rectangle  具体构件角色(ConcreteComponent),被装饰的对象
 * @Description:  
 * @author wwh 
 * @date 2022-9-1 16:13:36
 */
public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.err.println("Shape: Recatangle.");
    }

}
package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: ShapeDecorator  
 * @Description:  抽象装饰角色(Decorator),定义一组与抽象构件角色相同的行为,
 *                      通过实现接口来定义,并持有一个具体构件角色的引用,在完成装饰设计模式增加的功能之后再调用原有功能
 * @author wwh 
 * @date 2022-9-1 16:16:42
 */
public abstract class ShapeDecorator implements Shape{
    
    private Shape shape;
    
    public ShapeDecorator(Shape shape) {
        this.shape = shape;
    }

    @Override
    public void draw() {
        shape.draw();
    }

}
package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: RedShapeDecorator  
 * @Description: 具体的装饰者类,负责给被装饰者类扩展功能; 
 * @author wwh 
 * @date 2022-9-1 16:55:38
 */
public class RedShapeDecorator extends ShapeDecorator{

    public RedShapeDecorator(Shape shape) {
        super(shape);
    }
    
    @Override
    public void draw() {
        super.draw();
        setRedColor();
    }
    
    private void setRedColor() {
        System.err.println("Red Color!");
    }

}
package cn.com.pep.model.decarator.impl2;
/**
 * 
 * @Title: DecoratorPatternDemo  
 * @Description:  测试类
 * @author wwh 
 * @date 2022-9-1 16:56:54
 */
public class DecoratorPatternDemo {
    
    public static void main(String[] args) {
        Shape shape = new Rectangle();
        ShapeDecorator decorator = new RedShapeDecorator(shape);
        decorator.draw();
    }
}  

装饰设计模式在JDK源码中的应用:
  装饰设计模式在jdk源码中最具代表性的应用莫过于I/O体系中的InputStream/OutputStream,Reader/Writer等,现在我们就以InputStream为例进行分析:
1139198-20220902101054872-1690947339.png
抽象构件角色(Component):InputStream类,用来定义具体构件的行为;
具体构件角色(ConcreteComponent):FileInputStream、ByteArrayInputStream、ObjectInputStream类,具体被装饰的类;
抽象装饰角色(Decorator):FilterInputStream类,通过继承抽象构建角色类来定义一组与具体构件类相同的行为,再通过聚合的方式来持有被装饰角色的引用;
具体装饰角色(ConcreteDecorator):BufferedInputStream、DataInputStream、CheckedInputStream类,具体装饰者类,负责给被装饰者增加功能;

写在后面:
  装饰设计模式中,装饰者和被装饰者都可以独立扩展,没有耦合关系,被装饰者无需知道装饰者的存在,装饰者也无需关心被装饰者的具体细节,装饰设计模式可以动态扩展一个类的功能,
是继承的一种替代方案,但是装饰的层级过多可能比较复杂。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK