JAVA设计模式-装饰模式

装饰模式,顾名思义,就是美化、强化原有事物的意思。
增强功能,我们知道java的继承就可以实现,那要装饰模式干嘛?
区别就在”动态”,装饰模式可以动态的给对象增强,并且避免类爆炸。
试想,如果为实现一个特定功能,就要实现一个子类,那如果要实现很多功能,岂不是要很多子类,且一旦子类确定,其功能在编译时期就是确定的,是静态的。
在java中,IO就充分使用了该模式。我们看到了在java IO 中,有Reader、Writer、InputStream、OutputStream等抽象类,其他的类无非就是对这些类的装饰、增强。
装饰者与被装饰者拥有共同的超类。

举个例子:

我们想在网上买个手机,假如买的是苹果X,4000大洋,然后呢!只有裸机,我们又想买点配件来增强它的功能,网店上有很多配件,如:手机壳30大洋,Beats耳机500大洋等等。

我们现在用继承来处理这个问题,
定义一个手机抽象类,一个苹果手机类
手机抽象类:(Mobile.java)

package extend;
/**
 * 手机抽象类 
 */
public abstract class Mobile {

    /**
     * 手机名称
     */
    protected String name;
    /**
     * 价格
     */
    protected Double price;


    /**
     * 获取名称
     * @return
     */
    public abstract String getName();
    /**
     * 获取售价
     * @return
     */
    public abstract double getPrice();
}

苹果手机类(AppleMobile.java)

package extend;
/**
 * 苹果手机
 */
public class AppleMobile extends Mobile{

    @Override
    public double getPrice() {
        return this.price;
    }

    @Override
    public String getName() {
        return this.name;
    }

    public AppleMobile() {
        this.name = "苹果手机";
        this.price = 5000d;
    }
}

如果我们想多买个手机壳,就得实现一个子类

package extend;
/**
 * 手机壳+苹果手机 子类  
 */
public class MobileCaseAppleMobile extends AppleMobile{

    private String mobileCaseName(){
        return " + 手机壳";
    }

    private Double mobileCasePrice(){
        return 30d;
    }

    @Override
    public String getName() {
        return super.getName() + mobileCaseName();
    }

    @Override
    public double getPrice() {

        return super.getPrice() + mobileCasePrice();
    }
}
package extend;

public class Demo {

    public static void main(String[] args) {

        Mobile mobile = new MobileCaseAppleMobile();

        System.out.println(mobile.getName());
        System.out.println(mobile.getPrice());
    }
}

对应输出:
苹果手机 + 手机壳
5030.0

如果我们要买苹果手机+耳机呢?那就又要实现另外一个子类,就相当于一个个套餐(经常看到网店上有那种配套的套餐)。但是,当配件越来越多时,我们就要对应非常非常多的套餐,这中情况下,就会出现所谓的类爆炸。

如果使用装饰模式来处理呢?
我们定义一个手机抽象类,一个苹果手机类,一个配件装饰抽象类,一个耳机配件装饰类,一个手机壳配件装饰类。

手机抽象类:(Mobile.java)

package decorator;
/**
 * 手机抽象类 
 */
public abstract class Mobile {

    /**
     * 手机名称
     */
    protected String name;
    /**
     * 价格
     */
    protected Double price;


    /**
     * 获取名称
     * @return
     */
    public abstract String getName();
    /**
     * 获取售价
     * @return
     */
    public abstract double getPrice();
}

苹果手机类(AppleMobile.java)

package decorator;
/**
 * 苹果手机
 */
public class AppleMobile extends Mobile{

    @Override
    public double getPrice() {
        return this.price;
    }

    @Override
    public String getName() {
        return this.name;
    }

    public AppleMobile() {
        this.name = "苹果手机";
        this.price = 5000d;
    }
}

配件装饰抽象类(Accessories.java)

package decorator;
/**
 * 配件抽象类,这里继承并不是为了继承行为,而是类型
 */
public abstract class Accessories extends Mobile{

    /**
     * 配件修饰的手机
     */
    protected Mobile mobile;

    public Accessories(Mobile mobile) {
        this.mobile = mobile;
    }

    //获取配件名称
    public abstract String getDecoratorName();
}

耳机配件装饰类(Headset.java)

package decorator;
/**
 * 耳机配件装饰类 
 */
public class Headset extends Accessories{

    public Headset(Mobile mobile) {
        super(mobile);
    }

    @Override
    public String getName() {
        return mobile.getName() + "+" +getDecoratorName();
    }

    @Override
    public double getPrice() {
        return mobile.getPrice() + 500d;
    }

    @Override
    public String getDecoratorName() {

        return "Beats耳机";
    }
}

手机壳配件装饰类(MobileCase.java)

package decorator;
/**
 * 手机壳配件装饰类
 */
public class MobileCase extends Accessories{

    public MobileCase(Mobile mobile) {
        super(mobile);
    }

    @Override
    public String getName() {

        return mobile.getName() + "+" + getDecoratorName();
    }

    @Override
    public double getPrice() {

        return mobile.getPrice() + 30d;
    }

    @Override
    public String getDecoratorName() {
        return "手机壳";
    }
}
package decorator;

public class Demo {

    public static void main(String[] args) {

        Mobile mobile = new AppleMobile();
        System.out.println(mobile.getName());
        System.out.println(mobile.getPrice());
        mobile = new MobileCase(mobile);
        System.out.println(mobile.getName());
        System.out.println(mobile.getPrice());
        mobile = new Headset(mobile);
        System.out.println(mobile.getName());
        System.out.println(mobile.getPrice());
    }
}

对应输出:
苹果手机
5000.0
苹果手机+手机壳
5030.0
苹果手机+手机壳+Beats耳机
5530.0

如上,我们可以动态组合,动态增强我们需要的手机,如果我们只要苹果手机+手机壳

package decorator;

public class Demo {

    public static void main(String[] args) {

        Mobile mobile = new AppleMobile();
        mobile = new MobileCase(mobile);
        System.out.println(mobile.getName());
        System.out.println(mobile.getPrice());
    }
}

对应输出:
苹果手机+手机壳
5030.0

可以看出,我们使用装饰模式,当要新增加一个配件类型,我们就增加一个配件类。然后,在购买的时候,自由组合就行。

你可能感兴趣的:(设计模式,java设计模式,java)