结构型设计模式总结

  • 装饰模式

装饰(decorator)模式指的是在不改变原类文件和不使用继承的情况下,它是通过创建一个包装类,动态地扩展一个对象的功能。

装饰模式结构图
示例:

将一个Person对象通过包装类Decorator包装成含有各个属性(高、富、帅)的对象。

定义Person接口:

interface Person {

    void show();
}

需要进行合成的类:

class ConcreatePerson implements Person {

    @Override
    public void show() {
        System.out.println("人");
    }
}

抽象的装饰类:

/**
 * 创建Decorator类,持有Person对象,对Person的实例进行包装
 */
abstract class Decorator implements Person {
    protected Person person;

    public Decorator(Person person) {
        this.person = person;
    }

    @Override
    public abstract void show();
}

分别是高、富、帅的包装类:

class HeightDecorator extends Decorator {

    public HeightDecorator(Person person) {
        super(person);
    }

    @Override
    public void show() {
        height();
        person.show();
    }

    /**
     * 去修饰高属性
     */
    public void height() {
        System.out.println("高");
    }
}

class RichDecorator extends Decorator {

    public RichDecorator(Person person) {
        super(person);
    }

    @Override
    public void show() {
        rich();
        person.show();
    }

    public void rich() {
        System.out.println("富");
    }
}

class PrettyDecorator extends Decorator {

    public PrettyDecorator(Person person) {
        super(person);
    }

    @Override
    public void show() {
        pretty();
        person.show();
    }

    public void pretty() {
        System.out.println("帅");
    }
}

创建客户端执行测试:

    public static void main(String[] args) {
        //因为具体的Person和Decorator都继承过Person接口,所有两者可以相互替换
        //创建对象,创建需要的包装类,连续将包装过的装饰者继续装饰
        Person concreatePerson = new ConcreatePerson();
        Decorator decorator = new HeightDecorator(concreatePerson);
        Decorator decorator1 = new RichDecorator(decorator);
        Decorator decorator2 = new PrettyDecorator(decorator1);

        decorator2.show();
    }

打印结果:concreatePerson这个普通人在经过HeightDecorator、RichDecorator和PrettyDecorator三个装饰器包装之后,成为了一个高富帅。


装饰模式特点:

1.装饰对象和真实对象有相同的接口。这样调用者就能以和真实对象相同的方式与装饰对象交互。
2.装饰对象包含一个真实对象的引用。
3.装饰对象接受所有来自客户端的请求,它把这些请求转发给真实的对象。

装饰模式有缺点:

装饰模式和继承关系的目的都是要扩展对象的功能,但是Decorator可以比继承更加灵活,可以使用这些装饰类进行排列组合创造出很多不同行为的组合。

但是更灵活的代价是会创建很多装饰类,增加了更多的复杂性。

  • 代理模式

代理模式可以可以为其他对象提供一种代理以控制这个对象的访问。

代理模式结构图

Subject(抽象接口):真实主题与代理主题的共同接口。
RealSubject(目标类):定义了代理角色所代表的真实对象。
Proxy(代理类):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或之后执行某些操作,而不是单纯返回真实的对象。

示例:

Customer类为需要打官司的顾客,Lawyer为律师类,Lawyer类需要代理Customer打官司。

定义代理类与目标类共同的接口:

interface Law {
    //定义一个打官司的接口,需要实现打官司
    void law();
}

目标类:某个客户需要打官司

class Customer implements Law {

    @Override
    public void law() {
        System.out.println("上法庭陈述事实");
    }
}

代理类:律师,需要打官司,可以搜集证据,代理客户打官司

class Lawyer implements Law {
    private Customer customer;

    public Lawyer(Customer customer) {
        this.customer = customer;
    }

    /**
     * 陈述事实却需要当事人自己在法庭上陈述,自己调用law
     */
    @Override
    public void law() {
        collEvidence();
        //目标类调用自己方法
        customer.law();
        over();
    }

    /**
     * 律师可以做搜集证据
     */
    public void collEvidence() {
        System.out.println("搜集证据");
    }

    /**
     * 律师可以尽量打赢官司
     */
    public void over() {
        System.out.println("打赢官司");
    }
}

执行测试,律师代理客户打官司:

    public static void main(String[] args) {
        Customer customer = new Customer();
        Lawyer lawyer = new Lawyer(customer);
        lawyer.law();
    }

上面例子的代理方法是静态代理。加入有多个Customer具体目标类,每个目标类需要代理的law方法都不同,有的要打婚姻官司,有的打经济官司,有的打合同违约官司,那么就需要创建多个代理类,在内部去调用law1、law2、law3方法等。

动态代理:

见我的另一篇文章动态代理实战

  • 适配器模式

Adapter模式可以改变已有类(或外部类)的接口形式。

模式结构图:
示例:

场景需要18v的Target电压,但是总线是220v的Adapee电压,那么就需要一个适配器Adapter将220v的电压转为18v的电压。

Target类:

interface Target {

    void v18();
}

目标电压:

class Adapee220 {

    public void show() {
        System.out.println("输出220v电压");
    }
}

适配器Adapter类:

class Adapter implements Target {

    private Adapee220 adapee220;

    public Adapter(Adapee220 adapee220) {
        this.adapee220 = adapee220;
    }

    @Override
    public void v18() {
        adapee220.show();
        System.out.println("实现将220v电压转化为18v");
    }
}

执行测试:

    public static void main(String[] args) {

        Adapee220 adapee220 = new Adapee220();
        Target target = new Adapter(adapee220);
        target.v18();
    }

转化结果:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容