非常一个有意思的设计模式--装饰模式

  本文的主体是装饰模式,那么什么是装饰模式呢?在谈这个概念之前先给广大女朋友(理论上来说,所有未婚女性都有可能是我女朋友)送波礼物:

  收礼物应该是女同胞的最爱了,作为一个女孩子,肯定希望自己的男朋友可以给足惊喜。我知道很多男人是没有办法创造这种浪漫的氛围的,好吧,小林代劳了,送女孩子们一个礼物,大大的爱心!

在这里插入图片描述

  通过图我们可以很清晰的看到,红色盒子装着蓝色盒子,蓝色盒子又装着绿色盒子。绿色的盒子里装着我们的小心心。那么我们的小心心是不是就被装饰起来了呢?用绿色盒子装饰小心心,用蓝色盒子装饰绿色盒子,用红色盒子装饰蓝色盒子。看个图会更清晰!

在这里插入图片描述

  小林的一号女朋友收到礼物后非常的不满意,我不喜欢这种颜色嵌套,你把盒子的颜色倒过来我才喜欢。小林二话不说马上动手,十分钟小林的礼物变成这样:

在这里插入图片描述

  一号女朋友收到礼物后非常的开心,小林决定再做一份同样的礼物送给二号女朋友,说时迟那是快,直接送到二号女朋友脸前。二号女朋友打开礼物后,非常的不高兴,你不知道我喜欢深一点吗,为什么就套三个盒子,给我多套几个!小林为了满足二号女朋友修改了一下礼物,变成这样:

在这里插入图片描述

  二号女朋友一看是非常的开心那,我就喜欢这么深的礼物。

  我们来分析一下小林送礼物的整个流程。首先我们会看到不管是那种方式的哪一步,都会有一个同样的东西,那就是红心。而我们**在红心外面套盒子是为了让红心更漂亮,至于盒子怎么套,套几个是不是可以控制的呢?**对的,这就是我们说的装饰,装饰就是在原来的基础上去增加一些修饰性的东西。相信到此,大家对装饰已经有了明确的概念。接下来用《大话设计模式》中的案例来学习一下。

用户故事:我想要一个客户可以随意搭配服饰的装饰系统

完成这个系统我们需要有:

  1. 要有一个客户类,用于被修饰
  2. 要有很多的服装,供用户自由搭配

具体案例分析

第一版代码

@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();
}
}


已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页