设计模式之装饰模式(转)

  当我们想要扩展类的功能的时候,很多情况下会考虑用继承的方法,比如我有一个手机类,只支持打电话,如果我们想要扩展手机的功能,让普通的手机变成智能手机,那最简单的方式就是新建一个智能手机类并继  承手机类,扩充智能手机拥有的新功能,比如打飞机,玩愤怒的小鸟之类的。

  但是子类继承的方法总归不是非常灵活啊,为了更好的解决类功能扩展的问题,我们来引用今天要学习的新模式——装饰模式。首先先看一下标准定义。

   装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

   从这个定义中可以找到几个要点:

  1.动态的扩展

  2.不会改变原有类

  3.不用生成子类的继承方式

   在这个模式中主要有四大组件

  1.原始类接口(接口类型或者抽象类)

  2.原始类的具体实现类

  3.装饰器接口(一般类或抽象类)

  4.继承了装饰器接口的一系列具体装饰器

 

  对照以上这些组件来看一下类图表示。

二、UML类图

 

从UML中可以看到:具体实现类和装饰器基类都继承自原始类接口

 

下面我们来模拟一下将一部普通手机升级为智能手机和山寨智能手机的全过程。

原始类接口(接口类型或者抽象类)

/**
 * 手机总接口
 * @author rain
 *
 */
public interface Phone {
    //功能方法
    void feature();
}

原始类的具体实现类

/**
 * 一般的手机类
 * @author rain
 *
 */
public class CommonPhone implements Phone  {
    public void feature()  {
        System.out.println("能发短信和打电话.");
    }
}

装饰器接口

/**
 * 装饰基类
 * 
 * @author rain
 * 
 */
public class PhoneDecorator implements Phone {
    protected Phone phone;

    public PhoneDecorator(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void feature() {
        phone.feature();
    }
}

具体装饰器,需要重写基的feature() 方法,并添加自己的新功能

/**
 * 智能机修饰类
 * @author rain
 *
 */
public class AdvancedPhone extends PhoneDecorator{
    
    public AdvancedPhone(Phone phone){
        super(phone);
    }
    @Override
    public void feature()  {
        super.feature();
        System.out.println("可以玩愤怒的小鸟!");
    }

}
/**
 * 山寨机装饰类
 * @author rain
 *
 */
public class ShanZhaiPhone extends PhoneDecorator {
    public ShanZhaiPhone(Phone phone) {
        super(phone);
    }
    @Override
    public void feature() {
        super.feature();
        System.out.println("可以双卡双待!");
    }
}

客户端调用

/**
 * 在这个模式中主要有四大组件

  1.原始类接口(接口类型或者抽象类)
  2.原始类的具体实现类
  3.装饰器接口(一般类或抽象类)
  4.继承了装饰器接口的一系列具体装饰器
  装饰模式的特点

  装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。
  装饰对象包含一个真实对象的引用(reference)。
  装饰对象接收所有来自客户端的请求,它把这些请求转发给真实的对象。
  装饰对象可以在转发这些请求之前或之后附加一些功能。
  这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
 * @author rain
 *
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("-----------------------------普通手机-------------------------------");
        Phone commonPhone = new CommonPhone();
        commonPhone.feature();
        System.out.println("-----------------------------智能手机-------------------------------");
        // 将普通手机包一层智能的皮就成了智能手机
        AdvancedPhone advancedPhone = new AdvancedPhone(commonPhone);
        advancedPhone.feature();

        System.out.println("-----------------------------山寨手机-------------------------------");
        // 将普通手机包一层山寨的皮就成了强大的山寨手机
        ShanZhaiPhone shangZhaiPhone = new ShanZhaiPhone(commonPhone);
        shangZhaiPhone.feature();

        System.out.println("-----------------------------山寨智能手机----------------------------");
        // 将智能手机包一层山寨的皮就成了山寨智能机
        ShanZhaiPhone shangZhaiAdvancedPhone = new ShanZhaiPhone(new AdvancedPhone(new CommonPhone()));
        shangZhaiAdvancedPhone.feature();

    }
}

 

posted on 2015-01-09 13:27  hi_rain  阅读(315)  评论(0)    收藏  举报