【设计模式】设计模式——结构型
总览https://www.cnblogs.com/OhOfCourse/p/17163285.html
结构型,主要用于将类或对象进行组合从而构建灵活而高效的结构
注:从OneNote搬运过来,缺少一些UML图和代码示例。
一.适配器模式
1.0参考资料
1.1说明
将一个接口转换为客户希望的另一个接口,使接口不兼容的那些类可以一起工作,别名为包装器Wrapper
1.2示例
类适配器
Client想要调用sayHi接口而作为Server只能提供sayHello接口,因此用Adapter继承下Server且实现抽象的Target接口
1 public class Adapter extends Adaptee implements Target { 2 @Override 3 public void sayHi() { 4 super.sayHello(); 5 } 6 }
对象适配器
Adapter不再继承于Server而是像代理模式一样直接持有一个Server实例
1 public class Adapter implements Target { 2 // 目标类的对象 3 private Adaptee adaptee; 4 // 初始化适配器时可以指定目标类对象 5 public Adapter(Adaptee adaptee) { 6 this.adaptee = adaptee; 7 } 8 @Override 9 public void sayHi() { 10 adaptee.sayHello(); 11 } 12 }
1.3优缺点
二.桥接模式
2.0参考资料
2.1说明
含义
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
解析
一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。这种理解方式非常类似于,我们之前讲过的“组合优于继承”设计原则
角色
Abstraction:抽象化角色,定义出该角色的行为,同时保存一个对实现化角色的引用
Implementor:实现化角色,它是接口或者抽象类,定义角色必须的行为和属性
RefinedAbstraction:修正抽象化角色,引用实现化角色对抽象化角色进行修正
ConcreteImplementor:具体实现化角色,实现接口或抽象类定义的方法或属性
2.2示例
有一个Shape类,从它扩展出两个子类:Circle和Square。现在我想扩展这个类使这个类包含颜色比如Red和Blue。直接在Shape类上扩展就需要创建4个类才能覆盖所有的组合。这时如果我再增加一个颜色Yellow,这时组合就会增长成6个类。采用这种方式来扩展类,会导致代码的复杂程度指数级的增长。
对于上面这个例子,我们可以采用桥接模式进行重构。先从颜色维度抽象出Color类,然后在Shape类中添加一个指向某一颜色对象的引用成员变量(外包)。现在Shape类可以将所有与颜色相关的工作委派给边入的颜色对象。这个引用就成了Shape类和Color类的桥梁,此后我们再增加颜色就不需要修改Shape类。
1 interface iColor { 2 setColor(color: string): void; 3 } 4 class red implements iColor { 5 setColor(shape: String): void { 6 console.log(`${shape}颜色为red`); 7 } 8 } 9 class blue implements iColor { 10 setColor(shape: string): void { 11 console.log(`${shape}颜色为blue`); 12 } 13 } 14 abstract class Shape { 15 protected colorSetter: iColor;//作为桥接的引用 16 constructor(colorSetter: iColor) { 17 this.colorSetter = colorSetter; 18 } 19 abstract coloring(shape: string): void; 20 } 21 class Circle extends Shape { 22 constructor(colorSetter: iColor) { 23 super(colorSetter); 24 } 25 coloring() { 26 this.colorSetter.setColor("circle"); 27 } 28 } 29 class Square extends Shape { 30 constructor(colorSetter: iColor) { 31 super(colorSetter); 32 } 33 coloring() { 34 this.colorSetter.setColor("Square"); 35 } 36 } 37 const circle = new Circle(new red()); 38 const square = new Square(new blue()); 39 circle.coloring(); 40 square.coloring();
2.3优缺点
三.组合模式
3.0参考资料
3.1说明
定义
将对象组合成树状结构以表示 “部分-整体” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性
适用场景
需要表示一个对象整体或部分的层次结构
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
角色
Component(所有节点的抽象):所有对象(节点)的抽象或接口,用来定义所有节点的行为
Leaf(叶节点):树状结构中的叶节点(没有子节点),继承抽象并实现行为;
Composite(节点):树状结构中的根节点和子树的根节点,叶节点的容器,用来管理子节点。
简单对象和复合对象必须实现相同的接口
实现方式
(1)透明式
抽象节点中既定义了叶子的内容又定义了节点的内容,但叶子在实现时也需要实现节点部分的内容,这就造成了冗余、存在有可能的风险。
(2)安全式
抽象节点只定义叶子和节点的交集
3.2示例
1 class Program 2 { 3 /// <summary> 4 /// 该抽象类是文件夹抽象接口的定义,该类型相当于抽象构件Component类型。 5 /// </summary> 6 public abstract class TransparentMoodFolder 7 { 8 //增加文件夹或文件 9 public abstract void Add(TransparentMoodFolder folder); 10 11 //删除文件夹或者文件 12 public abstract void Remove(TransparentMoodFolder folder); 13 14 //打开文件夹或者文件,该操作相当于Component类型的Operation方法。 15 public abstract void Open(); 16 } 17 18 /// <summary> 19 /// 该Word文档类就是叶子构件的定义,该类型相当于Leaf类型,不能再包含子对象。 20 /// </summary> 21 public sealed class TransparentMoodWord : TransparentMoodFolder 22 { 23 //增加文件夹或文件 24 public override void Add(TransparentMoodFolder folder) 25 { 26 throw new Exception("Word文档不具有该功能。"); 27 } 28 29 //删除文件夹或者文件 30 public override void Remove(TransparentMoodFolder folder) 31 { 32 throw new Exception("Word文档不具有该功能。"); 33 } 34 35 //打开文件--该操作相当于Component类型的Operation方法 36 public override void Open() 37 { 38 Console.WriteLine("打开Word文档,开始进行编辑。"); 39 } 40 } 41 42 /// <summary> 43 /// SonFolder类型就是树枝构件,由于我们使用的是“透明式”,所以Add、Remove都是从Folder类型继承下来的。 44 /// </summary> 45 public class TransparentMoodSonFolder : TransparentMoodFolder 46 { 47 //增加文件夹或文件 48 public override void Add(TransparentMoodFolder folder) 49 { 50 Console.WriteLine("文件夹或者文件增加成功。"); 51 } 52 53 //删除文件夹或者文件 54 public override void Remove(TransparentMoodFolder folder) 55 { 56 Console.WriteLine("文件夹或者文件删除成功。"); 57 } 58 59 //打开文件夹--该操作相当于Component类型的Operation方法 60 public override void Open() 61 { 62 Console.WriteLine("打开文件夹。"); 63 } 64 } 65 66 static void Main(string[] args) 67 { 68 #region 组合模式之透明式 69 TransparentMoodFolder myword = new TransparentMoodWord(); 70 myword.Open(); //打开文件 71 //myword.Add(new TransparentMoodSonFolder()); //抛出异常 72 //myword.Remove(new TransparentMoodSonFolder()); //抛出异常 73 74 75 TransparentMoodFolder myfolder = new TransparentMoodSonFolder(); 76 myfolder.Open(); //打开文件夹 77 myfolder.Add(new TransparentMoodSonFolder()); //增加文件夹或者文件 78 myfolder.Remove(new TransparentMoodSonFolder()); //删除文件夹或者文件 79 80 Console.Read(); 81 #endregion 82 } 83 }
3.3优缺点
四.装饰模式
4.0参考资料
https://zhuanlan.zhihu.com/p/73478200
4.1说明
Decorator模式(别名Wrapper)
动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。
角色
(1)Component抽象构件,表示规范准备接收附加责任的对象
(2)ConcreteComponent具体构件
(3)Decorator装饰器,定义一个与抽象构件接口一致的接口
(4)ConcreteDecorator具体装饰器
使用场景
(1)需要扩展一个类的功能;
(2)需要动态地给一个对象增加功能,可随时撤销;
(3)排列组合产生的类太多,继承不现实。
4.2示例
https://zhuanlan.zhihu.com/p/73478200
4.3装饰模式和代理模式的异同点
相同点:都要维护一个Context用于接收被调用对象,对该对象的数据、行为进行包装
不同点:代理模式是对对象的行为进行封装,在流程上予以控制;装饰模式是在输出上予以封装,在输出结果上予以控制。
4.4装饰模式和适配器模式的区别
五.外观模式
5.0参考资料
5.1说明
对于一个拥有一个拥有若干子系统的系统,引入一个外观角色,为子系统的访问提供一个简单而单一的入口。客户端只需要与外观角色打交道,而不需要与系统内的很多子系统打交道。
系统中的各子系统并不需要知道外观角色的存在,它仅仅是另外一个客户端。
5.2示例
典型实现
1 外观角色+子系统 2 class Facade 3 { 4 private SubSystemA subSystemA = new SubSystemA(); 5 private SubSystemB subSystemB = new SubSystemB(); 6 private SubSystemC subSystemC = new SubSystemC(); 7 public void method() 8 { 9 subSystemA.method(); 10 subSystemB.method(); 11 subSystemC.method(); 12 } 13 } 14 class SubSystemA 15 { 16 public void method() 17 { 18 System.out.println("子系统A"); 19 } 20 } 21 class SubSystemB 22 { 23 public void method() 24 { 25 System.out.println("子系统B"); 26 } 27 } 28 class SubSystemC 29 { 30 public void method() 31 { 32 System.out.println("子系统C"); 33 } 34 }
引入抽象外观类
为了满足增删子系统的需求,避免修改外观类或客户端代码,借用模板方法模式的思想引入抽象外观类。
抽象外观类(抽象类或接口)负责对客户端提供交互接口,而对子系统的调用则由派生类来实现,也就是完全只是提供接口,不负责动作内容、动作顺序。
1 首先定义抽象外观类,接着具体外观类继承或者实线抽象外观类即可 2 interface AbstractFacade 3 { 4 void encrypt(String name); 5 } 6 class Facade1 implements AbstractFacade 7 { 8 private FileReader reader = new FileReader(); 9 private Encrypt1 encrypt1 = new Encrypt1(); 10 private FileWriter writer = new FileWriter(); 11 public void encrypt(String name) 12 { 13 reader.read(name); 14 encrypt1.encrypt(name); 15 writer.write(name); 16 } 17 } 18 class Facade2 implements AbstractFacade 19 { 20 private FileReader reader = new FileReader(); 21 private Encrypt2 encrypt2 = new Encrypt2(); 22 private FileWriter writer = new FileWriter(); 23 public void encrypt(String name) 24 { 25 reader.read(name); 26 encrypt2.encrypt(name); 27 writer.write(name); 28 } 29 } 30 客户端: 31 AbstractFacade facade = new Facade1(); 32 facade.encrypt("111"); 33 facade = new Facade2(); 34 facade.encrypt("222");
5.3优缺点
六.享元模式
6.0参考资料
6.1说明
6.2示例
6.3优缺点
七.代理模式
7.0参考资料
7.1说明
为其他对象提供一种代理以控制对这个对象的访问
7.2示例
7.3优缺点

浙公网安备 33010602011771号