设计模式 - 装饰者模式 Java&Kotlin

同算法与数据结构一样,设计模式同样是作为一个优秀程序员必须熟练掌握与应用的基本功,在阅读源码或者优秀的开源项目的同时,不难发现各种设计模式的灵活运用,叹为观止。

接下来一系列博客,将和大家一起分享这些常用的设计模式。

观察者模式

装饰者模式

工厂模式

单例模式

建造者模式​​​​​​​

本篇一起来看看装饰者模式是如何工作的,装饰者模式的概念,直接看起来个人认为是比较难以理解与应用的,不妨通过一个例子,一步步的感受装饰者模式的魅力。

本篇博客书写的时候,刚好就要到六一儿童节了,就以糖果屋为例子进行展开啦。

糖果屋的老板有不同的三种糖果,分别是巧克力糖、牛奶糖以及花生糖,同时有红色的糖纸和蓝色的糖纸,还有丝带与贴纸,不同的物件都有不同的价格,这个时候老板想在每一位小朋友选好之后,马上得出价格,老板心想:本boss也是996撸过码的人,不就是糖果的价格吗,设计一个基类Candy,然后用不同的糖果去继承,在组合出不同的价格就ok了,so easy!

但是在组合的时候,老板发现会有很多种组合,导致子类爆炸,例如红色盒子贴纸巧克力糖、蓝色盒子丝带牛奶糖、红色盒子两根丝带花生糖等等,如果以后要添加新的糖果,会导致组合数越来越多...

为了解决这个问题,老板又搬出了尘封已久的葵花宝典,直到看到了装饰者模式..

老板开始用装饰者模式开始设计了

首先,建立糖果的基类,有一个成员方法返回糖果的名字,一个抽象方法返回糖果的花费.

public abstract class Candy {
    protected String name;

    protected String getName() {
        return name;
    }

    public abstract double getCost();
}

然后使用具体的糖果去继承Candy

public class ChocolateCandy extends Candy {

    public ChocolateCandy() {
        name = "ChocolateCandy";
    }

    @Override
    public double getCost() {
        return 6.99;
    }
}
public class MilkCandy extends Candy {

    public MilkCandy() {
        name = "Milk Candy";
    }

    @Override
    public double getCost() {
        return 5.20;
    }
}
public class PeanutCandy extends Candy {

    public PeanutCandy() {
        name = "Peanut Candy";
    }

    @Override
    public double getCost() {
        return 6.66;
    }
}

有了具体的糖果之后,老板又开始定义核心组件装饰器

public abstract class CandyDecorate extends Candy{
    public abstract String getName();
}

定义好了装饰器,老板开始添加各种装饰组件:红色糖纸 蓝色糖纸 丝带 贴纸...

public class RedBox extends CandyDecorate {

    private Candy candy;

    public RedBox(Candy candy) {
        this.candy = candy;
    }

    @Override
    public String getName() {
        return candy.getName() + " with RedBox";
    }

    @Override
    public double getCost() {
        return 1.2 + candy.getCost();
    }
}
public class BlueBox extends  CandyDecorate {

    private Candy candy;

    public BlueBox(Candy candy) {
        this.candy = candy;
    }

    @Override
    public String getName() {
        return candy.getName() + " with blue box";
    }

    @Override
    public double getCost() {
        return 2.2 + candy.getCost();
    }
}
public class Ribbon extends CandyDecorate {

    private Candy candy;

    public Ribbon(Candy candy) {
        this.candy = candy;
    }

    @Override
    public String getName() {
        return candy.getName() + " with Ribbon";
    }

    @Override
    public double getCost() {
        return 0.5 + candy.getCost();
    }
}
public class Sticker extends CandyDecorate {

    private Candy candy;

    public Sticker(Candy candy) {
        this.candy = candy;
    }

    @Override
    public String getName() {
        return candy.getName() + " with sticker";
    }

    @Override
    public double getCost() {
        return 3.0 + candy.getCost();
    }
}

终于大功告成,老板开始了测试

public class CandyHouse {
    public static void main(String[] args) {
        Candy milkCandy = new MilkCandy();
        milkCandy = new BlueBox(milkCandy);
        milkCandy = new Ribbon(milkCandy);
        System.out.println(milkCandy.getName() + " ¥" + milkCandy.getCost());

        Candy chocolateCandy = new ChocolateCandy();
        chocolateCandy = new RedBox(chocolateCandy);
        chocolateCandy = new Sticker(chocolateCandy);
        System.out.println(chocolateCandy.getName() + " ¥" + chocolateCandy.getCost());
    }
}

通过装饰者模式,再也不用担心子类爆炸,可以方便快捷的对于基本的组件进行装饰.

下面是kotlin代码

abstract class Candy {

    var name = "unknown candy"

    fun geName(): String {
        return name
    }

    abstract fun cost(): Double
}

class MilkCandy() : Candy() {

    init {
        name = "Milk Candy"
    }

    override fun cost(): Double {
        return 3.88
    }

}

class PeanutCandy() : Candy() {
    init {
        name = "Peanut Candy"
    }

    override fun cost(): Double {
        return 5.55
    }
}

class ChocolateCandy() : Candy() {

    init {
        name = "Chocolate Candy"
    }

    override fun cost(): Double {
        return 2.88
    }
}

abstract class CandyDecorate : Candy() {
    abstract fun getCandyName(): String
}

class BlueBox(var candy: Candy) : CandyDecorate() {

    override fun getCandyName(): String {
        return candy.name + " with blue box"
    }

    override fun cost(): Double {
        return candy.cost() + 1.88
    }
}

class RedBox(var candy: Candy) : CandyDecorate() {
    override fun getCandyName(): String {
        return candy.name + " with red box"
    }

    override fun cost(): Double {
        return candy.cost() + 1.55
    }
}

fun main() {
    var chocolateCandy: Candy = ChocolateCandy()
    chocolateCandy = BlueBox(chocolateCandy)
    println(chocolateCandy.getCandyName() + " ¥" + chocolateCandy.cost())

    var milkCandy: Candy = MilkCandy()
    milkCandy = RedBox(milkCandy)
    println(milkCandy.getCandyName() + " ¥" + milkCandy.cost())
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值