设计模式之装饰模式

76 阅读2分钟

定义:

动态给的一个对象添加额外的职责或者功能。比生成子类更为灵活。

场景:

一份炒饭是5块钱,但是可以加任意的料,可以加鸡蛋,变成鸡蛋炒饭,还可以是香肠炒饭、腊肠炒饭、鸡蛋香肠炒饭……

如果按照原有子类结构设计,每一种炒饭都要生成一个新的子类,造成代码的庞大和臃肿。所以可以改用扩展方式。

先定义抽象类:

//抽象构件类
public interface IFood {
    String desc();
    int price();
}


//具体构建类
public class Chaofan implements IFood {
    @Override
    public String desc() {
        return "炒饭";
    }
    @Override
    public int price() {
	return 5;
    }
}

public class Chaomian implements IFood {
    @Override
    public String desc() {
        return "炒面";
    }
    @Override
    public int price() {
        return 6;
    }
}

//食材超类
public interface IFoodDecorator extends IFood {
}

//具体食材类
public class RoseDecorator implements IFoodDecorator {
    private IFood iFood;  //主食的引用,这样可以直接对主食的name和price做修改
    
    /**
     * 在构建食材的时候告诉是用于在什么主食中,
     * 我们只需要使用IFood接口就可以来修改主食的价格和描述,这就是IFood超类的好处
     * @param food
     */
    public RoseDecorator(IFood food) {
        this.iFood = food;
    }

    /**
     * 主食价格
     */
    @Override
    public int price() {
        /**在主食本来具有的价格上增加 5 元**/
        return iFood.price() + 5;
    }

    /**
     * 主食描述
     */
    @Override
    public String desc() {
        /**在主食本来具有的描述上增加 '肉丝' 描述 **/
        return "肉丝" + iFood.desc();
    }
}
public class EggDecorator implements IFoodDecorator {
    private IFood iFood;

    public EggDecorator(IFood food) {
        this.iFood = food;
    }

    @Override
    public int price() {
        return iFood.price() + 2;
    }

    @Override
    public String desc() {
        return "鸡蛋" + iFood.desc();
    }
}

测试:

public class testDecorator {
    public static void main(String[] args) {
        IFood iFood1 = new RoseDecorator(new ChaoFan());
        System.out.println(iFood1.desc);
        System.out.println(iFood1.price);

        IFood iFood2 = new EggDecorator(new Chaomian());
        System.out.println(iFood2.desc);
        System.out.println(iFood2.price);
    }
}

总结:

装饰者模式对于扩展功能来说很好,比如我们的炒饭,我们需要添加牛肉食材,我们只需新建一个实现了IFoodDecorator 接口的类,并在两个方法中作出自己的修改就可以了,这样就把牛肉食材增加了,如果我们要增加炒粉,那就增加一个实现了IFood接口的炒粉类实现对应的方法就可以了,是不是很方便,很好扩展,还不用修改之前的