Java 设计模式 (6)

定义一个抽象类,此类的实现类都需要使用 DrawAPI:

public abstract class Shape { protected DrawAPI drawAPI; protected Shape(DrawAPI drawAPI){ this.drawAPI = drawAPI; } public abstract void draw(); }

定义抽象类的子类:

// 圆形 public class Circle extends Shape { private int radius; public Circle(int radius, DrawAPI drawAPI) { super(drawAPI); this.radius = radius; } public void draw() { drawAPI.draw(radius, 0, 0); } } // 长方形 public class Rectangle extends Shape { private int x; private int y; public Rectangle(int x, int y, DrawAPI drawAPI) { super(drawAPI); this.x = x; this.y = y; } public void draw() { drawAPI.draw(0, x, y); } }

最后,我们来看客户端演示:

public static void main(String[] args) { Shape greenCircle = new Circle(10, new GreenPen()); Shape redRectangle = new Rectangle(4, 8, new RedPen()); greenCircle.draw(); redRectangle.draw(); }

可能大家看上面一步步还不是特别清晰,我把所有的东西整合到一张图上:

Java 设计模式

这回大家应该就知道抽象在哪里,怎么解耦了吧。桥梁模式的优点也是显而易见的,就是非常容易进行扩展。

装饰模式

要把装饰模式说清楚明白,不是件容易的事情。也许读者知道 Java IO 中的几个类是典型的装饰模式的应用,但是读者不一定清楚其中的关系,也许看完就忘了,希望看完这节后,读者可以对其有更深的感悟。

首先,我们先看一个简单的图,看这个图的时候,了解下层次结构就可以了:

Java 设计模式

我们来说说装饰模式的出发点,从图中可以看到,接口 Component其实已经有了 ConcreteComponentA 和 ConcreteComponentB 两个实现类了,但是,如果我们要增强这两个实现类的话,我们就可以采用装饰模式,用具体的装饰器来装饰实现类,以达到增强的目的。

从名字来简单解释下装饰器。既然说是装饰,那么往往就是添加小功能这种,而且,我们要满足可以添加多个小功能。最简单的,代理模式就可以实现功能的增强,但是代理不容易实现多个功能的增强,当然你可以说用代理包装代理的方式,但是那样的话代码就复杂了。

首先明白一些简单的概念,从图中我们看到,所有的具体装饰者们 ConcreteDecorator

都可以作为 Component 来使用,因为它们都实现了 Component 中的所有接口。它们和 Component 实现类 ConcreteComponent 的区别是,它们只是装饰者,起装饰作用,也就是即使它们看上去牛逼轰轰,但是它们都只是在具体的实现中加了层皮来装饰而已。

注意这段话中混杂在各个名词中的 Component 和 Decorator,别搞混了。

下面来看看一个例子,先把装饰模式弄清楚,然后再介绍下 java io 中的装饰模式的应用。

最近大街上流行起来了“快乐柠檬”,我们把快乐柠檬的饮料分为三类:红茶、绿茶、咖啡,在这三大类的基础上,又增加了许多的口味,什么金桔柠檬红茶、金桔柠檬珍珠绿茶、芒果红茶、芒果绿茶、芒果珍珠红茶、烤珍珠红茶、烤珍珠芒果绿茶、椰香胚芽咖啡、焦糖可可咖啡等等,每家店都有很长的菜单,但是仔细看下,其实原料也没几样,但是可以搭配出很多组合,如果顾客需要,很多没出现在菜单中的饮料他们也是可以做的。

在这个例子中,红茶、绿茶、咖啡是最基础的饮料,其他的像金桔柠檬、芒果、珍珠、椰果、焦糖等都属于装饰用的。当然,在开发中,我们确实可以像门店一样,开发这些类:LemonBlackTea、LemonGreenTea、MangoBlackTea、MangoLemonGreenTea......但是,很快我们就发现,这样子干肯定是不行的,这会导致我们需要组合出所有的可能,而且如果客人需要在红茶中加双份柠檬怎么办?三份柠檬怎么办?万一有个变态要四份柠檬,所以这种做法是给自己找加班的。

不说废话了,上代码。

首先,定义饮料抽象基类:

public abstract class Beverage { // 返回描述 public abstract String getDescription(); // 返回价格 public abstract double cost(); }

然后是三个基础饮料实现类,红茶、绿茶和咖啡:

public class BlackTea extends Beverage { public String getDescription() { return "红茶"; } public double cost() { return 10; } } public class GreenTea extends Beverage { public String getDescription() { return "绿茶"; } public double cost() { return 11; } } ...// 咖啡省略

定义调料,也就是装饰者的基类,此类必须继承自 Beverage:

// 调料 public abstract class Condiment extends Beverage { }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzsfxy.html