小滴课堂-学习笔记:(7)你知道结构型设计模式装饰器+代理模式 ?留下来聊聊

56 篇文章 0 订阅
32 篇文章 1 订阅

logo 愿景:"让编程不再难学,让技术与生活更加有趣"


更多架构课程请访问 xdclass.net

 

目录

第1集 如虎添翼的设计模式-装饰器设计模式介绍

第2集 满足老王的改装搭配-玩转装饰器设计模式案例实战

第3集 JDK源码里面的Stream IO流-装饰器设计模式应用

第4集 加盟商来啦-你需要掌握的代理设计模式《上》

第5集 加盟商来啦-你需要掌握的代理设计模式《下》

第6集 大量使用第三方SDK-它们常用的外观设计模式你知道多少?

第7集 案例实战-外观设计模式在多渠道消息推送里面的应用

第8集 Flyweight Pattern享元设计模式你知道多少

第9集 老王接网站外包-享元设计模式案例实战和优缺点

干货文档


简介:讲解-装饰器设计模式介绍和应用场景

  • 装饰器设计模式(Decorator Pattern)

    • 也叫包装设计模式,属于结构型模式,它是作为现有的类的一个包装,允许向一个现有的对象添加新的功能,同时又不改变其结构
    • 给对象增加功能,一般两种方式 继承或关联组合,将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为来增强功能,这个就是装饰器模式,比继承模式更加灵活

 

  • 应用场景

    • 小滴课堂-老王,本来计划买跑车撩妹的,结果口袋没钱,改买自行车,为了显得突出,店家提供多种改装方案,加个大的喇叭、加个防爆胎等,经过装饰之后成为目的更明确的自行车,更能解决问题。像这种不断为对象添加装饰的模式就叫 Decorator 模式,Decorator 指的是装饰物。

      image-20200929172954093

    image-20200929172749200

    • 以动态、透明的方式给单个对象添加职责,但又能不改变其结构

    • JDK源码里面应用的最多的就是IO流,大量使用装饰设计模式

       

      image-20200929170148219

  • 角色(装饰者和被装饰者有相同的超类(Component))

    • 抽象组件(Component)

      • 定义装饰方法的规范,最初的自行车,仅仅定义了自行车的API;

       

    • 被装饰者(ConcreteComponent)

      • Component的具体实现,也就是我们要装饰的具体对象
      • 实现了核心角色的具体自行车

       

    • 装饰者组件(Decorator)

      • 定义具体装饰者的行为规范, 和Component角色有相同的接口,持有组件(Component)对象的实例引用

      • 自行车组件 都有 名称和价格

         

       

    • 具体装饰物(ConcreteDecorator)

      • 负责给构件对象装饰附加的功能
      • 比如 喇叭,防爆胎

 

 

 

 

 

 

 

 

 

 

 

第2集 满足老王的改装搭配-玩转装饰器设计模式案例实战

简介:装饰器设计模式案例实战

  • 背景需求



小滴课堂-老王,由于公司发了项目奖金,不够买跑车,就先买自行车,店家里面 有小号、中号、大号等规格的自行车。
​
然后改造加一个喇叭,后来不够又要加多一个,一个防爆胎不够,又有两个,存在很多个随机组合的改装。 
​
店家就苦恼了,这样的结构难搞,价格也难算,而且需求再变动,就更麻烦了。
​
使用装饰者就可以解决这个问题

image-20200929170148219

  • 不采用设计模式,你会怎么做?自己试试,然后看是否够灵活

 

  • 采用装饰器设计模式编码实战

 

 

  • 优点

    • 装饰模式与继承关系的目的都是要扩展对象的功能,但装饰模式可以提供比继承更多的灵活性。
    • 使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,原有代码无须改变,符合“开闭原则”
  • 缺点

    • 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂 (多层包装)
    • 增加系统的复杂度,加大学习与理解的难度

 

  • 装饰器模式和桥接模式对比

    • 相同点都是通过封装其他对象达到设计的目的,和对象适配器也类似,有时也叫半装饰设计模式

    • 没有装饰者和被装饰者的主次区别,桥接和被桥接者是平等的,桥接可以互换,不用继承自同一个父类

      比如例子里面的,可以是Phone持有Color,也可以是Color持有Phone

    image-20200928224524790

    • 桥接模式不用使用同一个接口;装饰模式用同一个接口装饰,接口在父类中定义

       

       

 

 

 

 

 

 

 

第3集 JDK源码里面的Stream IO流-装饰器设计模式应用

简介:讲解-装饰器设计模式在JDK源码里面应用场景

  • 抽象组件(Component):InputStream

    • 定义装饰方法的规范

     

  • 被装饰者(ConcreteComponent) : FileInputStream 、ByteArrayInputStream

    • Component的具体实现,也就是我们要装饰的具体对象

     

  • 装饰者组件(Decorator):FilterInputStream

    • 定义具体装饰者的行为规范, 和Component角色有相同的接口,持有组件(Component)对象的实例引用
    • 自行车组件 都有 名称和价格

     

  • 具体装饰物(ConcreteDecorator):BufferedInputStream、DataInputStream

    • 负责给构件对象装饰附加的功能
    • 比如 喇叭,防爆胎

image-20200929172105246

  • 应用场景



//添加了Buffer缓冲功能
InputStream inputStream = new BufferedInputStream(new FileInputStream(""));






 

第4集 加盟商来啦-你需要掌握的代理设计模式《上》

简介:讲解代理设计模式,让代理帮你完成工作《上》

  • 代理设计模式(Proxy Pattern)

    • 为其他对象提供一种代理以控制对这个对象的访问,属于结构型模式。

    • 客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象

       

 

  • 应用场景

    • 各大数码专营店,代理厂商进行销售对应的产品,代理商持有真正的授权代理书
    • 客户端不想直接访问实际的对象,或者访问实际的对象存在困难,通过一个代理对象来完成间接的访问
    • 想在访问一个类时做一些控制,或者增强功能

timg

  • 角色

    • Subject: 抽象接口,真实对象和代理对象都要实现的一个抽象接口,好比销售数码产品
    • Proxy: 包含了对真实对象的引用,从而可以随意的操作真实对象的方法,好比 代理加盟店
    • RealProject :真实对象,好比厂商销售数码产品

image-20201002093501076

 

 

 

 

 

 

第5集 加盟商来啦-你需要掌握的代理设计模式《下》

简介:讲解代理设计模式,让代理帮你完成工作《下》

  • 业务需求



小滴课堂-老王,想开个数码小卖部,为以后退休生活做准备,代理各大厂商的手机和电脑,用代理设计模式帮他实现下
​
Subject 卖手机
​
RealProject 苹果、华为厂商,核心是卖手机,但是选址不熟悉
​
Proxy 老王数码专卖店:代理卖手机,附加选地址,增加广告等
​
​
编码实战




/**
 * 抽取公共的方法
 */
public interface DigitalSell {
​
    void sell();
}
​
​
/**
 * 小滴课堂,愿景:让技术不再难学
 *
 * @Description 真实的对象
 * @Author 二当家小D
 * @Remark 有问题直接联系我,源码-笔记-技术交流群
 * @Version 1.0
 **/
​
public class DigitalSellReal implements DigitalSell{
​
    @Override
    public void sell() {
​
        System.out.println("销售华为手机");
    }
}
​
​
/**
 * 小滴课堂,愿景:让技术不再难学 https://xdclass.net
 *
 * @Description 代理对象,增加了功能
 * @Author 二当家小D
 * @Remark 有问题直接联系我,源码-笔记-技术交流群 微信 xdclass6
 * @Version 1.0
 **/
​
public class DigitalSellProxy implements DigitalSell {
​
    private DigitalSell realObj = new DigitalSellReal();
​
    @Override
    public void sell() {
​
        makeAddress();
        realObj.sell();
        makeAD();
    }
    private void makeAddress(){
        System.out.println("一个人流量很高的地址");
    }
    private void makeAD(){
        System.out.println("投放广告");
    }
​
}
​
//使用
public static void main(String[] args) {
​
        //真实对象的行为
        DigitalSell realObj = new DigitalSellReal();
        realObj.sell();
​
        //代理对象的行为
        DigitalSell proxy = new DigitalSellProxy();
        proxy.sell();
    }
  • 优点

    • 可以在访问一个类时做一些控制,或增加功能
    • 操作代理类无须修改原本的源代码,符合开闭原则,系统具有较好的灵活性和可扩展性
  • 缺点

    • 增加系统复杂性和调用链路

image-20201002113748302

  • 有静态代理和动态代理两种

    • 动态代理也有多种方式,cglib、jdk,可以看看新版Springboot专题的spring5模块

     

  • 和装饰器模式的区别:

    • 代理模式主要是两个功能

      • 保护目标对象
      • 增强目标对象,和装饰模式类似了

 

 

 

 

 

第6集 大量使用第三方SDK-它们常用的外观设计模式你知道多少?

简介:讲解外观设计模式的介绍和应用场景

  • 外观设计模式 Facade Pattern

    • 门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口
    • 定义了一个高层接口,这个接口使得这系统更加容易使用

image-20201002105704370

 

 

  • 应用场景

    • 在外人看来,小滴课堂-老王是负责消息推送这个工作,看起来很轻松,但他们不知道里面有多复杂,老王加班多久才输出一个统一的接口,只要轻松操作就可以完成复杂的事情
    • 开发里面MVC三层架构,在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间使用interface接口进行交互,不用担心内部逻辑,降低耦合性
    • 各种第三方SDK大多会使用外观模式,通过一个外观类,也就是整个系统的接口只有一个统一的高层接口,这对用户屏蔽很多实现细节,外观模式经常用在封装API的常用手段
    • 对于复杂难以维护的老系统进行拓展,可以使用外观设计模式
    • 需要对一个复杂的模块或子系统提供一个外界访问的接口,外界对子系统的访问只要黑盒操作

 

  • 角色

    • 外观角色(Facade):客户端可以调用这个角色的方法,这个外观方法知道多个子系统的功能和实际调用
    • 子系统角色(SubSystem):每个子系统都可以被客户端直接调用,子系统并不知道门面的存在,

image-20201002113738990

 

 

 

 

 

 

 

 

 

 

第7集 案例实战-外观设计模式在多渠道消息推送里面的应用

简介:讲解外观设计模式的案例实战

  • 业务需求



在外人看来,小滴课堂-老王是负责消息推送这个工作,看起来很轻松,但他们不知道里面有多复杂
​
需要对接微信消息、邮件消息、钉钉消息等,老王加班长期加班没有女友,才输出一个统一的接口,只要轻松操作就可以完成复杂的事情
​
用外观设计模式帮老王完成这个需求

 

image-20201002113646079

  • 优点

    • 减少了系统的相互依赖,提高了灵活性

    • 符合依赖倒转原则

      • 针对接口编程,依赖于抽象而不依赖于具体
    • 符合迪米特法则

      • 最少知道原则,一个实体应当尽量少地与其他实体之间发生相互作用
  • 缺点

    • 增加了系统的类和链路
    • 不是很符合开闭原则,如果增加了新的逻辑,需要修改facade外观类

 

 

 

 

 

 

第8集 Flyweight Pattern享元设计模式你知道多少

简介:讲解享元设计模式的介绍和应用场景

  • 享元设计模式(Flyweight Pattern)

    • 属于结构型模式,主要用于减少创建对象的数量,以减少内存占用和提高性能, 它提供了减少对象数量从而改善应用所需的对象结构的方式。
    • 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象

 

  • 应用场景

    • JAVA 中的 String,如果字符串常量池里有则返回,如果没有则创建一个字符串保存在字符串常量池里面
    • 数据库连接池、线程池等
    • 如果系统有大量相似对象,或者需要用需要缓冲池的时候可以使用享元设计模式,也就是大家说的池化技术
    • 如果发现某个对象的生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享对象,减少实例的个数

 

  • 内部状态

    • 不会随环境的改变而有所不同,是可以共享的
  • 外部状态

    • 不可以共享的,它随环境的改变而改变的,因此外部状态是由客户端来保持(因为环境的变化一般是由客户端引起的)

 

  • 角色

    • 抽象享元角色:为具体享元角色规定了必须实现的方法,而外部状态就是以参数的形式通过此方法传入
    • 具体享元角色:实现抽象角色规定的方法。如果存在内部状态,就负责为内部状态提供存储空间。
    • 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键
    • 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外部状态

image-20201004120620154

 

 

 

 

 

 

 

 

 

第9集 老王接网站外包-享元设计模式案例实战和优缺点

简介:讲解享元设计模式的案例实战和优缺点

  • 案例实战



小滴课堂-老王为了增加收入,开始接了外包项目,开发了一个AI网站模板,可以根据不同的客户需求自动生成不同类型的网站
电商类、企业产品展示、信息流等。
​
在部署的时候就麻烦了,是不是每个机器都用租用云服务器,购买独立域名呢
​
这些网站结构相似度很高,而且都不是高访问量网站,可以先公用服务器资源,减少服务器资源成本,类似虚拟机或者Docker




public class Company {
​
    private String name;
​
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
​
    public Company(){}
​
    public Company(String name){
        this.name = name;
    }
}
//抽象接口,
public abstract class CloudWebSite {
​
    public abstract void run(Company company);
​
}
​
/**
 * 小滴课堂,愿景:让技术不再难学 https://xdclass.net
 *
 * @Description
 * @Author 二当家小D
 * @Remark 有问题直接联系我,源码-笔记-技术交流群  微信 xdclass6
 * @Version 1.0
 **/
public class ConcreteWebSite extends CloudWebSite {
    private String category;
​
    public  ConcreteWebSite(String category){
        this.category = category;
    }
​
    @Override
    public void run(Company company) {
        System.out.println("网站分类:"+category+", 公司:"+company.getName());
​
    }
}
​
​
//工厂
public class WebSiteFactory {
    /**
     * map里面的key是分类
     */
    private Map<String,ConcreteWebSite> map = new HashMap<>();
    /**
     * 根据key获取分类站点
     * @param category
     * @return
     */
    public CloudWebSite getWebSiteByCategory(String category){
​
        if(map.containsKey(category)){
            return map.get(category);
        }else {
            ConcreteWebSite site = new ConcreteWebSite(category);
            map.put(category,site);
            return site;
        }
    }
    /**
     * 获取分类个数
     * @return
     */
    public int getWebsiteCategorySize(){
        return map.size();
    }
​
}
​
​
//使用
public static void main(String[] args) {
​
        WebSiteFactory factory = new WebSiteFactory();
​
        CloudWebSite companySite1 =  factory.getWebSiteByCategory("企业官网");
        companySite1.run(new Company("小滴课堂"));
​
        CloudWebSite companySite2 =  factory.getWebSiteByCategory("企业官网");
        companySite2.run(new Company("旭瑶课堂"));
​
        CloudWebSite byteDanceSite =  factory.getWebSiteByCategory("信息流");
        byteDanceSite.run(new Company("字节跳动"));
​
        CloudWebSite ucNews =  factory.getWebSiteByCategory("信息流");
        ucNews.run(new Company("优视科技"));
​
        System.out.println("网站分类总数:" +factory.getWebsiteCategorySize());
​
​
    }


  • 优点

    • 大大减少了对象的创建,降低了程序内存的占用,提高效率

     

  • 缺点

    • 提高了系统的复杂度,需要分离出内部状态和外部状态

 

  • 注意划分内部状态和外部状态,否则可能会引起线程安全问题,必须有一个工厂类加以控制

 

  • 享元设计模式和原型、单例模式的区别

    • 原型设计模式是指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
    • 单例设计模式保证一个类仅有一个实例

 

 

 

干货文档

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dev666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值