【设计模式】设计模式——结构型

总览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();
View Code

 

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     }
View Code

 

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 }
View Code

引入抽象外观类

为了满足增删子系统的需求,避免修改外观类或客户端代码,借用模板方法模式的思想引入抽象外观类。
抽象外观类(抽象类或接口)负责对客户端提供交互接口,而对子系统的调用则由派生类来实现,也就是完全只是提供接口,不负责动作内容、动作顺序。

 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");
View Code

 

5.3优缺点

 

六.享元模式

6.0参考资料

 

6.1说明

 

6.2示例

 

6.3优缺点

 

七.代理模式

7.0参考资料

 

7.1说明

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

7.2示例

 

7.3优缺点

  

posted @ 2023-02-28 11:18  啊原来是这样呀  阅读(11)  评论(0)    收藏  举报