设计模式之结构型模式

2023-05-16

文章目录

    • 结构型模式(Structural Pattern)
      • 1. 适配器模式(Adapter/Wrapper Pattern)
      • 2. 桥接模式(Bridge Pattern)
      • 3. 装饰模式(Decorator Pattern)
      • 4. 外观模式(Facade Pattern)
      • 5. 享元模式(Flyweight Pattern)
      • 6. 代理模式(Proxy Pattern)
      • 7. 组合模式(Composite Pattern)

结构型模式(Structural Pattern)

结构型模式关注的是类和对象之间的组合。结构型模式可以分为类结构型和对象结构型。类结构型模式关心类的组合,一般只存在继承和实现关系,通过多个类组成更大的类;对象结构型关心类与对象的组合,通过关联关系在一个类中定义另一个类的实例对象并调用其方法。根据合成复用原则,多关联而少继承,故此,大部分结构型模式是对象结构型模式。

1. 适配器模式(Adapter/Wrapper Pattern)

适配器模式将接口转换为客户希望的另一个接口,使不兼容的类一起工作。适配器提供客户类需要的接口,将客户类的请求转化为对适配者相应接口的调用。
适配器模式包含四个角色:目标抽象类定义客户要用的特定领域的接口;适配器类可以调用另一个接口,作为一个转换器,对适配者和抽象目标类进行适配,它是适配器模式的核心;适配者类是被适配的角色,它定义了一个已经存在的接口,这个接口需要适配;在客户类中针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法。
类适配器模式中适配器类要同时继承目标抽象类和适配者类,在目标抽象类的方法中调用适配者类的方法。
对象适配器模式中适配器类继承目标抽象类,并定义一个适配者对象,在目标抽象类的方法中调用适配者对象的方法。
接口适配器模式,当不需要全部实现接口的方法时,先设计一个抽象类,将结构的方法实现为空,用抽象类的子类有选择的覆盖父类方法。

A. 适配器模式的实现
1)类适配器模式
在这里插入图片描述

2)对象适配器模式
在这里插入图片描述

public class AdapterPatternDemo {
  public static void main(String[] arg) {
    Battery b = new Battery();
    b.charge(new VoltageAdapter());
    b.charge(new VoltageAdapterII());
  }
}

public class Battery {
  //电池只能使用低电压充电
  void charge(LowVoltage lv) {
    System.out.print("转化后的电压:"+lv.getLow());
  }
}
public class HighVoltage {
  private int highVoltageValue;
  
  public HighVoltage() {
    highVoltageValue = 100;
  }
  public HighVoltage(int val) {
    highVoltageValue = val;
  }
  public int getHigh() {
    return highVoltageValue;
  }
}
public interface LowVoltage {
  public int getLow() {}
}

//类适配器模式
public class VoltageAdapter extends HighVoltage implements LowVoltage {
  static int scale = 10;
  public int getLow() {
    return getHigh() / scale;
  }
}

//对象适配器
public class VoltageAdapterII implements LowVoltage {
  //成员变量也可以通过构造函数引入
  HighVoltage hv = new HighVoltage(1000);
  static int scale = 10;
  public int getLow() {
    return hv.getHigh() / scale;
  }
}

B. 适配器模式的优缺
优:将目标类与适配者解耦,提高适配者复用性,拓展性好,符合开闭原则
缺:不能将适配者类及其子类都适配到目标接口,java至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类

C. 适配器模式的适用场景
现有类的接口不符合系统需要
一个重复适用的类,与一些关联度低的类关联

2. 桥接模式(Bridge Pattern)

桥接模式将继承关系转换为关联关系,把抽象化与实现化解耦,使得二者可以独立变化(下图中红色与绿色框可单独变化)。举个例子,比如有三种形状(圆形,三角形,矩形),每个形状三种颜色(红,绿,蓝)。按照继承关系则需要九个类满足所有情况。而采用桥接模式在需要六个类,将两种类别桥接在一起(把两种类按照引用的方式联系在一起)。

桥接模式包含如下四个角色:
抽象类(Abstraction)中定义了一个实现类接口类型的对象并可以维护该对象;
扩充抽象类(RefinedAbstraction)扩充由抽象类定义的接口,它实现了在抽象类中定义的抽象业务方法,在扩充抽象类中可以调用在实现类接口中定义的业务方法;
实现类接口(Implementor)定义了实现类的接口,实现类接口仅提供基本操作,而抽象类定义的接口可能会做更多更复杂的操作;
具体实现类(ConcreteImplementor)实现了实现类接口并且具体实现它,在不同的具体实现类中提供基本操作的不同实现,在程序运行时,具体实现类对象将替换其父类对象,提供给客户端具体的业务操作方法。

桥接模式和适配器模式用于设计的不同阶段,桥接模式用于系统的初步设计,对于存在两个独立变化维度的类可以将其分为抽象化和实现化两个角色,使它们可以分别进行变化;而在初步设计完成之后,当发现系统与已有类无法协同工作时,可以采用适配器模式。
在这里插入图片描述

A. 桥接模式的实现

public class BridgePatternDemo {
  public static void main(String[] arg) {
    Shape circleR = new Circle(new Red());
    Shape circleG = new Circle(new Green());
    circle.show();
    //可以加新的形状
    //Shape square = new Square(new Red());
  }
}
//抽象类层
public abstract class Shape {
  private Color clr;
  public Shape(Color c) {
    clr = c;
  }
  public abstract void show() {}
}
public class Circle extends Shape {
  private String shape;
  public Circle(Color c) {
    super(c);
    shape = "Circle";
  }
  public void show() {
    System.out.printf("Shape is %s, Color is %s", this.shape, c.getColor());
  }
}

//接口层
public interface Color {
  public String getColor();
}
public class Red implements Color {
  public String getColor() {
    return "Red";
  }
}
public class Green implements Color {
  public String getColor() {
    return "Green";
  }
}

B. 桥接模式的优缺
优:分离了抽象接口及其实现部分;提高系统的扩充性
缺:聚合关系在抽象层,系统的设计理解复杂度增加
C. 桥接模式的使用场景
系统需在抽象层和实现层增加灵活性,避免两个层次之间建立静态继承关系
一个类存在两个独立变化的维度,且这两个维度都需要扩展
抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响

3. 装饰模式(Decorator Pattern)

装饰模式动态地给已有对象增加一些新的功能而不改变原有结构。装饰模式可在不想增加很多子类的情况下扩展类。就增加功能来说,装饰器模式相比生成子类更为灵活。

一般给对象增加行为的方式包括继承机制,即静态的使子类在拥有父类方法的同时还拥有自身的方法。用户不能控制增加行为的方式和时机。关联机制,即把一个对象嵌入另一个对象中,通过调用嵌入嵌入对象的方法扩展自己的行为。
在这里插入图片描述

A. 装饰者模式的实现

public class DecoratorDemo {
  public void main(String[] arg) {
    Item item = new Candy();
    System.out.print(item.contents());
    
    //用纸包糖
    item = new Paper(item);
    System.out.print(item.contents());
    
    //再包一层纸盒
    item = new Box(item);
    System.out.print(item.contents());
  }
}

public abstract class Item {
  public String name;
  public void setName(String name) {
    this.name = name;
  }
  public String getName() {
    return this.name;
  }
  public abstract String contents();
}
public class Decorator extends Item{
  public Item item;
  public Decorator(Item item) {
    this.item = item;
  }
  public String contents() {
    return super.getName() + item.contents();
  }
}

public class Candy extends Item{
  public Candy() {
    setName("candy");
  }
  public String contents() {
    return getName();
  }
}
public class Paper extends Decorator {
  public Paper(Item item) {
    super(item);
    setName("paper");
  }
}
public class Box extends Decorator {
  public Box(Item item) {
    super(item);
    setName("box");
  }
}

B. 装饰者模式的优缺
优:动态扩展对象功能,装饰类与构建类可独立变化,符合开闭原则
缺:易出错,产生很多装饰者;装饰类的接口要与被装饰类接口保持一致
C. 装饰者模式的使用场景
在不影响其他对象条件下,需动态给对象增加功能,动态撤销。

4. 外观模式(Facade Pattern)

外观模式的用意是为子系统提供一个集中化和简化的沟通渠道。外观模式中,外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面。外观对象是在客户端直接调用的角色,在外观对象中可以知道相关的子系统的功能和责任,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理;每一个子系统可以是一个类的集合。举个例子,去医院看病,会有挂号,问诊,取药等流程,得去不同得部门,而分诊台就是直接与病人交互得外观对象。
在这里插入图片描述

A. 外观模式的实现

public class FacadeDemo {
  public void main(String[] arg) {
    Helper helper = new Helper();
    helper.register("zhangsan");
    helper.getMedicine();
  }
}

public class Helper {
  private RegPart r;
  private MedPart m;
  public void register(String name) {
    r.signUp(name);
  }
  public void getMedicine() {
    m.getMedicine();
  }
}
public class RegPart {
  private String name;
  public void signUp(String name) {
    this.name = name;
  }
}
public class MedPart {
  public void getMedicine() {
    System.out.println("your medicine");
  }
}

B. 外观模式的优缺
优:对客户屏蔽子系统,易操作,降低客户与子系统之间的耦合
缺:增加新的子系统可能需要修改外观类,不符合开闭原则

C, 外观模式的适应场景
为一个复杂子系统提供一个简单接口时或者客户程序与多个子系统之间存在很大的依赖性可以使用外观模式

5. 享元模式(Flyweight Pattern)

享元模式是一个考虑系统性能的设计模式,当系统中对象数量过多时会导致运行代价过高,享元模式通过共享技术实现相似对象的复用以减少系统中对象的数量。其中,可以共享的相同内容称为内部状态;不能共享的内容称为外部状态,一般由客户端保存,在享元对象创建后,在需要时传入享元对象内。一般具有相同内部状态的享元对象存储在享元池中,通常由一个享元工厂(工厂模式)来维护,享元模式的核心就在于这个享元工厂类,当用户需要对象时,先在享元池中找,如果没有则创建新对象并加入享元池。由于共享内部状态一般有限,故享元对象较小,亦称细粒度对象,享元模式亦称轻量级模式(蝇量模式)。享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。

在这里插入图片描述

FlyWeight:抽象享元类,定义了对象的内外部状态
ConcreteFlyWeight:具体享元类,具体的产品对象
UnsharedConcreteFlyWeight:非共享具体享元类,不出现在享元工厂中
FlyWeightFactory:享元工厂类,维护一个集合存储享元对象

A. 享元模式的实现

 public class FlyWeightPatternDemo {
   public static void main(String[] arg) {
     
     FlyWeightFactory factory = new FlyWeightFactory();
     FlyWeight fw1 = factory.getFlyWeight("1");
     fw1.showName();
     FlyWeight fw2 = factory.getFlyWeight("2");
     fw2.showName();
     FlyWeight fw3 = factory.getFlyWeight("1");
     fw3.showName();
   }
 }
 
public class FlyWeightFactory {
  private Map<String, FlyWeight> map;
  public FlyWeightFactory() {
    map = new HashMap<String, FlyWeight>();
  }
  
  public FlyWeight getFlyWeight(String name) {
    FlyWeight fw = map.get(name);
    if(fw == null) {
      fw = new ConcreteFlyWeight(name);
      map.put(name, fw);
    }
    return fw;
  }
}

public interface FlyWeight {
  public void showName() {}
}
public class ConcreteFlyWeight implements FlyWeight {
  private String name;
  public ConcreteFlyWeight(String name) {
    this.name = name;
  }
  public void showName() {
    System.out.print(name);
  }
}

B. 享元模式的优缺
优:减少内存中对象数量;内部,外部状态独立,享元对象可在不同环境下被共享
缺:系统逻辑变得复杂,要分离出内部状态和外部状态
C. 享元模式的适用场景
系统中大量相同或相似对象,且这类对象被大量使用。对象的大部分状态可以外部化。java中string就是享元模式。

6. 代理模式(Proxy Pattern)

当一些对象无法直接引用时(权限问题等等),需要通过一个第三方代理来间接引用,通过代理对象去掉客户不想或不能看到的部分,或者添加额外的功能,间接操作真实对象。代理模式的动机便是给对象提供一个代理,由代理对象控制原对象。

1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了便于控制。

在这里插入图片描述

抽象主题角色声明了真实主题和代理主题的共同接口;
代理主题角色内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象;
真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作客户端可以通过代理主题角色间接调用真实主题角色中定义的方法

A. 代理模式的实现

public class ProxyPatternDemo {
  public static void main(String[] arg) {
    Subject sb = new ProxySubject("file.doc");
    
    //从磁盘加载文件
    sb.show();
    //不在从磁盘加载
    sb.show();
  }
}

public interface Subject {
  public void show();
}
public class RealSubject implements Subject {
  private String fileName;
  public RealSubject(String name) {
    fileName = name;
  }
  public void show() {
    System.out.println(fileName);
  }
}
public class ProxySubject implements Subject {
  private String fileName;
  private RealSubject realSubject;
  
  public ProxySubject(String name) {
    fileName = name;
  }
  public void show() {
    if(realSubject == null) {
      realSubject = new RealSubject(fileName);
    }
    realSubject.show();
  }
}

B. 代理模式的优缺
优:降低耦合度,高扩展
缺:可能出现速度缓慢,实现复杂的情况
C. 代理模式适用场景
远程代理,虚拟代理(用小对象代替消耗大的对象,在真正使用时才创建大对象),缓冲代理,保护代理,防火墙代理,动态代理(AOP)

7. 组合模式(Composite Pattern)

组合模式又叫整体部分模式,通过树形结构来组合对象(对象有层次结构),用于表示部分以及整体层次。组合模式将要处理的对象表示成一棵树形结构,系统要对树中的分支节点和叶子节点进行操作,组合模式使得用户对单个对象和组合对象的访问具有一致性。

在这里插入图片描述

Compontent:对象接口,实现了所有对象共有的行为。
Composite:分支节点,维护一个容器保存子节点。
Leaf:叶子节点,不再有子节点了即为分支节点的特例,分支为0。

A. 组合模式的实现

//以学校组织管理系统为例,有学校>学院>系
public abstract class OrganizationComponent {
   
   private String name;
   
   public OrganizationComponent(String name) {
     this.name = name;
   }
   public void add(OrganizationCompontent o) {
     //默认实现,因为叶子节点不需要该函数
   }
   public void delete(OrganizationCompontent o) {
     //默认实现,因为叶子节点不需要该函数
   }
   public String getName() {
     return this.name;
   }
   public abstract void print();
}

public class University extends OrganizationCompontent {
   List<OrganizationCompontent> list = new ArrayList<>();
   
   public University(String name) {
     super(name);
   }
   public void add(OrganizationCompontent o) {
     list.add(o);
   }
   public void delete(OrganizationCompontent o) {
     list.remove(o);
   }
   public void print() {
     for(OrganizationCompontent o : list) {
       o.print();
     }
   }
}

public class College extends OrganizationCompontent {
   List<OrganizationCompontent> list = new ArrayList<>();
   
   public College(String name) {
     super(name);
   }
   public void add(OrganizationCompontent o) {
     list.add(o);
   }
   public void delete(OrganizationCompontent o) {
     list.remove(o);
   }
   public void print() {
     for(OrganizationCompontent o : list) {
       o.print();
     }
   }
}

public class Department extends OrganizationCompontent {
  public Department(String name) {
    super(name);
  }
  public void print() {
    System.out.print(getName());
  }
}

public class CompositePatternDemo {
  public static void main(String[] arg) {
    
    OrganizationCompontent university = new University("西安交通大学");
    
    OrganizationCompontent infoCollege = mew College("信息工程学院");
    OrganizationCompontent softwareCollege = mew College("软件学院");
    
    infoCollege.add(new Department("电子"));
    infoCollege.add(new Department("计算机"));
    
    softwareCollege.add(new Department("软件工程"));
    softwareCollege.add(new Department("大数据"));
    
    university.add(infoCollege);
    university.add(softwareCollege);
    
    //打印学校组织结构
    university.print();
    //打印信息学院组织结构
    infoCollege.print();
  }
}

B. 组合模式的优缺
优:可自由添加节点
缺:一般叶子和分支的声明都是实现类,而不是接口,违反了依赖倒置原则

C. 组合模式的适用场景
表示的对象具有层次结构(嵌套),需要用统一的接口访问组合对象或者单个对象。比如树形菜单结构或者文件夹管理操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之结构型模式 的相关文章

随机推荐

  • ssm——小学期实训总结

    实训总结 经过这两个星期短暂的学习 xff0c 我学习了ssm的框架搭建与web前端设计基础 在第一个星期 xff0c 老师着重为我们讲了框架的原理 搭建与运用 xff1b 而在第二个星期 xff0c 重点则转移到了小组对项目的开发与研究上
  • 节点中心性

    文章目录 度中心性 Degree Centrality 特征向量中心性 Eigenvector Centrality Katz中心性 Katz Centrality Katz index PageRank中心性PageRank算法 接近中心
  • 机器学习面试知识点总结

    文章目录 计算学习理论过拟合与欠拟合过拟合欠拟合 偏差与方差最大似然估计与贝叶斯估计极大似然估计贝叶斯决策论贝叶斯估计 特征工程与特征选择特征工程逐层归一化特征选择 模型融合融合策略 评估方法与评价指标评估方法评价指标 优化算法正则化深度模
  • Multi-view graph convolutional networks with attention mechanism

    摘要 传统的图卷积网络关注于如何高效的探索不同阶跳数 hops 的邻居节点的信息 但是目前的基于GCN的图网络模型都是构建在固定邻接矩阵上的即实际图的一个拓扑视角 当数据包含噪声或者图不完备时 xff0c 这种方式会限制模型的表达能力 由于
  • An Empirical Study of Graph Contrastive Learning

    摘要 图对比学习在图表示学习领域树立了新的范式 xff0c 不需要人工标注信息 但对GCL的分析却寥寥无几 本文通过分析一般化的GCL范式的各个部分包括增强函数 xff0c 对比模式 xff0c 对比目标和负采样技术 xff0c 然后分析各
  • Data Augmentation

    自监督深度学习模型的精确性严重依赖于训练时数据的多样性和数据量 模型要想在更复杂任务上有较好的效果一般会有大量的隐藏单元 一般在训练过程中训练隐藏单元越多需要的数据越多 xff0c 即任务复杂度与参数量与需要的数据量成正比 由于训练复杂任务
  • Semi-Supervised and Self-Supervised Classification with Multi-View Graph Neural Networks

    摘要 图神经网络在图结构数据中取得了很好的效果但是大多数的模型使用的还是叫浅层的结构 xff0c 当模型层数加深时很容易过平滑 本文基于多视图来聚合更多的信息 我们首先设计两个互补的视图来描述全局结构和节点特征相似性 xff0c 然后使用注
  • GCC: Graph Contrastive Coding for Graph Neural Network Pre-Training

    摘要 目前图表示学习在许多任务上取得了很好的效果但是都是关注于具体领域的并不具有迁移性 本文借鉴预训练思想 xff0c 设计了一个自监督图神经网络框架来在多个网络中捕获一般化的网络拓扑结构属性 我们设计的预训练任务是在多个网络之间判别子图实
  • Graph Contrastive Learning with Adaptive Augmentation

    摘要 对比学习在无监督图表示学习中取得了很好的效果 xff0c 大部分图对比学习首先对输入图做随机增强生成两个视图然后最大化两个视图表示的一致性 其中 xff0c 图上的增强方式是非常重要的部分鲜有人探索 我们认为数据增强模式应该保留图固有
  • A Survey on Graph Structure Learning: Progress and Opportunities

    文章目录 摘要引言预备知识GSL pipline Graph Structure ModelingMetric based ApproachesNeural ApproachesDirect Approaches Postprocessin
  • 图构造总结-Graph‑based semi‑supervised learning via improving the quality of the graph dynamically

    前言 本博文主要对论文中提到的图构造方法进行梳理 xff0c 论文自己提出的模型并未介绍 xff0c 感兴趣的可以阅读原文 摘要 基于图的半监督学习GSSL主要包含两个过程 xff1a 图的构建和标签推测 传统的GSSL中这两个过程是完全独
  • 超图构造综述,Hypergraph Learning: Methods and Practices

    文章目录 摘要引言基础知识Hypergraph GenerationDistance based hypergraph generationRepresentation based hypergraph generationAttribut
  • 图论基础知识总结

    文章目录 图的概念路图的代数表示邻接矩阵可达矩阵完全关联矩阵拉普拉斯矩阵对称归一化拉普拉斯矩阵随机游走归一化拉普拉斯矩阵 欧拉图与汉密尔顿图平面图对偶与着色数与生成树最小生成树算法 xff1a 根树图的存储邻接矩阵邻接表十字链表邻接多重表
  • 图增强与图对比学习

    文章目录 对比学习数据增强基于特征的增强基于结构的增强基于采样的增强自适应的增强 代理任务同尺度对比跨尺度对比 目标函数参考 CSDN排版太垃圾了 xff0c 点此连接去知乎看吧 xff01 xff01 xff01 xff01 xff01
  • K-Core, K-Shell & K-Crust傻傻分不清楚

    K Core算法是用于在图中寻找符合一定紧密关系条件的子图结构的算法 xff0c 通常用于进行子图划分 xff0c 去除不重要的结点 参考论文k core Theories and applications ScienceDirect K
  • 社区发现算法总结

    图划分指将网络顶点划分为指定规模 xff0c 指定数量的非重叠群组 xff0c 使得群组之间的边数最小 图划分时 xff0c 群组的数量和规模是固定的 社区发现不同于图划分的是网络群组的数量和规模不是由实验者确定的 xff0c 而是由网络本
  • 机器学习面经--常见问题

    csdn的排版真的太垃圾了 xff0c 想看的移步知乎 1 xff0c Normalization 数据标准化处理主要包括数据同趋化处理和无量纲化处理两个方面 数据同趋化处理主要解决不同性质数据问题 xff0c 对不同性质指标直接加总不能正
  • 设计模式之创建型模式

    文章目录 创建型模式 Creational Pattern 1 1单例模式 Singleton Pattern 1 2工厂模式 Factory Pattern 1 3抽象工厂模式 Abstract Factory Pattern 1 4建造
  • 设计模式之行为型模式

    文章目录 行为型模式 Behavioral Pattern 1 观察者模式 Observer Pattern 2 中介者模式 Mediator Pattern 3 访问者模式 Visitor Pattern 4 状态模式 State Pat
  • 设计模式之结构型模式

    文章目录 结构型模式 Structural Pattern 1 适配器模式 Adapter Wrapper Pattern 2 桥接模式 Bridge Pattern 3 装饰模式 Decorator Pattern 4 外观模式 Faca