非常一个有意思的设计模式--装饰模式
本文的主体是装饰模式,那么什么是装饰模式呢?在谈这个概念之前先给广大女朋友(理论上来说,所有未婚女性都有可能是我女朋友)送波礼物:
收礼物应该是女同胞的最爱了,作为一个女孩子,肯定希望自己的男朋友可以给足惊喜。我知道很多男人是没有办法创造这种浪漫的氛围的,好吧,小林代劳了,送女孩子们一个礼物,大大的爱心!
通过图我们可以很清晰的看到,红色盒子装着蓝色盒子,蓝色盒子又装着绿色盒子。绿色的盒子里装着我们的小心心。那么我们的小心心是不是就被装饰起来了呢?用绿色盒子装饰小心心,用蓝色盒子装饰绿色盒子,用红色盒子装饰蓝色盒子。看个图会更清晰!
小林的一号女朋友收到礼物后非常的不满意,我不喜欢这种颜色嵌套,你把盒子的颜色倒过来我才喜欢。小林二话不说马上动手,十分钟小林的礼物变成这样:
一号女朋友收到礼物后非常的开心,小林决定再做一份同样的礼物送给二号女朋友,说时迟那是快,直接送到二号女朋友脸前。二号女朋友打开礼物后,非常的不高兴,你不知道我喜欢深一点吗,为什么就套三个盒子,给我多套几个!小林为了满足二号女朋友修改了一下礼物,变成这样:
二号女朋友一看是非常的开心那,我就喜欢这么深的礼物。
我们来分析一下小林送礼物的整个流程。首先我们会看到不管是那种方式的哪一步,都会有一个同样的东西,那就是红心。而我们**在红心外面套盒子是为了让红心更漂亮,至于盒子怎么套,套几个是不是可以控制的呢?**对的,这就是我们说的装饰,装饰就是在原来的基础上去增加一些修饰性的东西。相信到此,大家对装饰已经有了明确的概念。接下来用《大话设计模式》中的案例来学习一下。
用户故事:我想要一个客户可以随意搭配服饰的装饰系统
完成这个系统我们需要有:
- 要有一个客户类,用于被修饰
- 要有很多的服装,供用户*搭配
具体案例分析
第一版代码
@Data
public class Person {
// 名字
private String name;
public Person(String name){
this.name=name;
}
public void wearTShirts(){
System.out.print("大T恤 ");
}
public void wearBigTrouser(){
System.out.print("垮裤 ");
}
public void wearSneakers(){
System.out.print("破球鞋 ");
}
public void wearSuit(){
System.out.print("西装 ");
}
public void wearTie(){
System.out.print("领带 ");
}
public void wearLeatherShoes(){
System.out.print("皮鞋 ");
}
public void show(){
System.out.println("装扮的" + name);
}
}
public class MainTest {
public static void main(String[] args) {
Person xiaoLin = new Person("小林");
xiaoLin.wearTie();
xiaoLin.wearBigTrouser();
xiaoLin.wearSuit();
xiaoLin.show();
}
}
首先看一下UML类图(现在大家对着代码应该能看的懂,后期后专门出一篇讲UML),非常简单就一个类,但是它是否存在问题呢?
这个代码实现了功能,但是却把各种服饰放到了一个类中,这就违背了开发中的单一职责原则(这个类一个职责是创建一个人,另一个职责是可以穿各种各样的服饰)。这还不是最主要的,如果以后每加一个服饰,那么就要打开这个类修改,这又违反了开发中的开闭原则,尽管不可能完全的对修改关闭,但是也要尽量去遵循这个原则。这个时候原则大家可以想想如何修改第一版代码,使其可以满足单一职责跟开闭原则。
第二版代码
首先看下第二版代码的UML类图,这样会不会清晰很多,首先Person跟服饰分开了,并且将服饰抽象成一个类,具体的服装都来实现这个服饰类,这样新加一些服饰,直接写一个类继承服饰类即可,这样我们就达到了对修改关闭,对扩展开放的原则。但是我还是要说现在代码还是可优化的,具体如何优化,各位看官看完下面的代码可以思考一下!
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public void show(){
System.out.println("装扮的" + name);
}
}
public abstract class Finery {
abstract void show();
}
public class BigTrouser extends Finery {
@Override
void show() {
System.out.print("垮裤 ");
}
}
public class LeatherShoes extends Finery {
@Override
void show() {
System.out.print("皮鞋 ");
}
}
public class Sneakers extends Finery {
@Override
void show() {
System.out.print("破球鞋 ");
}
}
public class Suit extends Finery {
@Override
void show() {
System.out.print("西装 ");
}
}
public class Tie extends Finery {
@Override
void show() {
System.out.print("领带 ");
}
}
public class TShirts extends Finery {
@Override
void show() {
System.out.print("大T恤 ");
}
}
public class MainTest {
public static void main(String[] args) {
Person xiaoLin = new Person("小林");
Finery suit = new Suit();
Finery bigTrouser = new BigTrouser();
Finery tshirts = new TShirts();
suit.show();
bigTrouser.show();
tshirts.show();
xiaoLin.show();
}
}
第三版代码
我们发现在main里面我们的是这么写的,suit.show(),bigTrouser.show(),调用者都是不一样的。这样相当于我们在穿衣服的过程中是暴露的,你穿衣服的过程都让人尽收眼底。所以这样是不太合适的,我们应该是**将衣服在内部全部穿好,然后进行展示。**我们来看下UML图
public class Person {
private String name;
public Person(){
}
public Person(String name){
this.name = name;
}
public void show(){
System.out.println("装扮的" + name);
}
}
public class Decorator extends Person {
protected Person component;
public void decorate(Person component){
this.component = component;
}
@Override
public void show() {
if (component != null){
component.show();
}
}
}
public class BigTrouser extends Decorator {
@Override
public void show() {
System.out.print("垮裤 ");
super.show();
}
}
public class LeatherShoes extends Decorator {
@Override
public void show() {
System.out.print("皮鞋 ");
super.show();
}
}
public class Sneakers extends Decorator {
@Override
public void show() {
System.out.print("破球鞋 ");
super.show();
}
}
public class Suit extends Decorator {
@Override
public void show() {
System.out.print("西装 ");
super.show();
}
}
public class Tie extends Decorator {
@Override
public void show() {
System.out.print("领带 ");
super.show();
}
}
public class TShirts extends Decorator {
@Override
public void show() {
System.out.print("大T恤 ");
super.show();
}
}
接下来看看控制台代码如何写,首先创建穿衣服的人xiaoLin,接下来就是new几个具体服饰对象,sneakers,bigTrouser,tShirts,然后最重要是decorate()方法,这个方法传入的Person对象,然后在Decorator类中维护一个Person对象。然后将通层层包装,将具体服饰对象一层一层的包装,由最后一个对象tShirts调用一次show方法即可,不必像第二版代码一样调用了四次show方法。
tips:可能有小伙伴不明白为什么具体服饰对象可以传进decorate()方法,原因很简单,因为具体服饰类的的爹的爹是Person,可以结合上面的UML图看。
public class MainTest3 {
public static void main(String[] args) {
Person xiaoLin = new Person("小林");
Sneakers sneakers = new Sneakers();
BigTrouser bigTrouser = new BigTrouser();
TShirts tShirts = new TShirts();
sneakers.decorate(xiaoLin);
bigTrouser.decorate(sneakers);
tShirts.decorate(bigTrouser);
tShirts.show();
}
}
Sneakers sneakers = new Sneakers();
BigTrouser bigTrouser = new BigTrouser();
TShirts tShirts = new TShirts();
sneakers.decorate(xiaoLin);
bigTrouser.decorate(sneakers);
tShirts.decorate(bigTrouser);
tShirts.show();
}
}
上一篇: 一次Git撤销错误的Merge
下一篇: 那些有意思的网站彩蛋
推荐阅读