结构型模式
1、代理模式
场景:
某对象具有保护的内容或调用复杂,不应直接被访问。
定义:
给某对象提供一个代理以控制对该对象的访问。即通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
目的:
起到中介作用,保护目标对象。
使调用和目标对象分离,降低系统耦合。
代码示例:
/// <summary>
/// 代理模式
/// </summary>
public class Proxy
{
//抽象主题
public interface Subject
{
public void Request();
}
//真实主题
public class RealSubject : Subject
{
public void Request()
{
Console.WriteLine("RealSubject");
}
}
//代理
public class RealSubjectProxy : Subject
{
private RealSubject RealSubject;
public void Request()
{
if (RealSubject == null)
{
RealSubject = new RealSubject();
}
PreRequest();
RealSubject.Request();
PostRequest();
}
public void PreRequest()
{
Console.WriteLine("预处理");
}
public void PostRequest()
{
Console.WriteLine("后续处理");
}
}
/*
调用方式:
RealSubjectProxy proxy = new RealSubjectProxy();
proxy.Request();
*/
}
2、适配器模式
场景:
一个类型需要适配多种功能。
定义:
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
目的:
将目标类适配新的功能,并满足开闭原则。
代码示例:
/// <summary>
/// 适配器模式
/// </summary>
public class Adapter
{
/// <summary>
/// 打印接口
/// </summary>
/// <remarks>
/// 目标接口(需要适配的接口)
/// </remarks>
public interface Print
{
void Print();
}
/// <summary>
/// 人类
/// </summary>
/// <remarks>
/// 适配者(被适配的类型)
/// </remarks>
public class Person
{
public string GetName()
{
return "ABC";
}
}
/// <summary>
/// 人输出适配器类
/// </summary>
/// <remarks>
/// 结构型适配器,继承需要适配的类型并实现需要适配的接口
/// </remarks>
public class PersonPrintAdapter : Person, Print
{
/// <summary>
/// 输出人的名称
/// </summary>
public void Print()
{
Console.WriteLine(GetName());
}
}
/*
调用方式:
Print print = new PersonPrintAdapter();
print.Print();
*/
/// <summary>
/// 人输出适配器类
/// </summary>
/// <remarks>
/// 对象型适配器
/// </remarks>
public class PersonPrintObjectAdapter : Print
{
private Person Person;
public PersonPrintObjectAdapter(Person person)
{
this.Person = person;
}
public void Print()
{
Console.WriteLine(Person.GetName());
}
}
/*
调用方式:
Person person = new Person();
Print print = new PersonPrintObjectAdapter(person);
print.Print();
*/
}
3、桥接模式
场景:
一个类内部具备两种或多种变化维度,且这些维度都需要进行扩展。
定义:
将抽象属性与实现分离,使它们可以独立变化。
目的:
将目标类桥接多个维度的属性和实现,并满足开闭原则。
解决继承关系在多个维度下数量很多且扩展困难的问题。
代码示例:
/// <summary>
/// 桥接模式
/// </summary>
public class Bridge
{
/// <summary>
/// 颜色
/// </summary>
public interface Color
{
public string GetColor();
}
/// <summary>
/// 红色
/// </summary>
/// <remarks>
/// 扩展颜色
/// </remarks>
public class Red : Color
{
public string GetColor()
{
return "Red";
}
}
/// <summary>
/// 蓝色
/// </summary>
/// <remarks>
/// 扩展颜色
/// </remarks>
public class Blue : Color
{
public string GetColor()
{
return "Blue";
}
}
/// <summary>
/// 材质
/// </summary>
public interface Texture
{
public string GetTexture();
}
/// <summary>
/// 棉质
/// </summary>
/// <remarks>
/// 扩展材质
/// </remarks>
public class Cotton : Texture
{
public string GetTexture()
{
return "Cotton";
}
}
/// <summary>
/// 涤纶
/// </summary>
/// <remarks>
/// 扩展材质
/// </remarks>
public class Polyester : Texture
{
public string GetTexture()
{
return "Polyester";
}
}
/// <summary>
/// 商品抽象
/// </summary>
public abstract class Commodity
{
protected Color Color { get; set; }
protected Texture Texture { get; set; }
public void SetColor(Color color)
{
this.Color = color;
}
public void SetTexture(Texture texture)
{
this.Texture = texture;
}
public abstract void Print();
}
/// <summary>
/// A商品
/// </summary>
/// <remarks>
/// 扩展抽象
/// </remarks>
public class ACommodity : Commodity
{
public override void Print()
{
Console.WriteLine($"A:{Color.GetColor()}:{Texture.GetTexture()}");
}
}
/// <summary>
/// B商品
/// </summary>
/// <remarks>
/// 扩展抽象
/// </remarks>
public class BCommodity : Commodity
{
public override void Print()
{
Console.WriteLine($"B:{Color.GetColor()}:{Texture.GetTexture()}");
}
}
/*
调用方式:
Color color = new Red();
Texture texture = new Polyester();
Commodity commodity = new ACommodity();
commodity.SetColor(color);
commodity.SetTexture(texture);
commodity.Print();
*/
}
4、装饰器模式
场景:
在不改变现有对象结构的情况下,动态地给该对象增加一些额外功能的模式。
定义:
在不改变现有对象结构的情况下,动态地给该对象增加一些额外功能的模式。
目的:
不改变原有对象的情况下,动态的给一个对象扩展功能。
代码示例:
/// <summary>
/// 装饰器模式
/// </summary>
public class Decorator
{
/// <summary>
/// 抽象产品
/// </summary>
public interface Product
{
public void PrintName();
}
/// <summary>
/// 食物
/// </summary>
/// <remarks>具体产品</remarks>
public class Food : Product
{
public void PrintName()
{
Console.WriteLine("Food");
}
}
/// <summary>
/// 抽象装饰器
/// </summary>
public class ProductDecorator : Product
{
private Product Product;
public ProductDecorator(Product product)
{
this.Product = product;
}
public virtual void PrintName()
{
this.Product.PrintName();
}
}
/// <summary>
/// 价格装饰器
/// </summary>
/// <remarks>装饰器具体实现</remarks>
public class PriceProductDecorator : ProductDecorator
{
public PriceProductDecorator(Product product) : base(product)
{
}
public override void PrintName()
{
base.PrintName();
//添加打印价格的功能
Console.WriteLine("Price: 100$");
}
}
/*
调用方式:
Product product = new Food();
Product decorator = new PriceProductDecorator(product);
decorator.PrintName();
*/
}
5、外观模式
场景:
多个子系统具有复杂组合流程。
定义:
将多个子系统组合为一个新的接口,使外部调用不用关心内部子系统的具体细节。
目的:
将多个子系统组合为一个新的接口。
缺点:
增加新的子系统可能需要修改外观类的源代码,违背了开闭原则。
代码示例:
/// <summary>
/// 外观模式
/// </summary>
public class Facade
{
/// <summary>
/// 吃饭
/// </summary>
/// <remarks>子系统</remarks>
public class Eat
{
public void Do()
{
Console.WriteLine("Eat");
}
}
/// <summary>
/// 睡觉
/// </summary>
/// <remarks>子系统</remarks>
public class Sleep
{
public void Do()
{
Console.WriteLine("Sleep");
}
}
/// <summary>
/// 玩
/// </summary>
/// <remarks>子系统</remarks>
public class Play
{
public void Do()
{
Console.WriteLine("Sleep");
}
}
/// <summary>
/// 一天要做的事
/// </summary>
/// <remarks>外观模式</remarks>
public class OneDayFacade
{
private Eat Eat = new Eat();
private Sleep Sleep = new Sleep();
private Play Play = new Play();
/// <summary>
/// 组合执行
/// </summary>
public void Do()
{
Eat.Do();
Sleep.Do();
Play.Do();
}
}
/*
调用方式:
OneDayFacade oneDayFacade = new OneDayFacade();
oneDayFacade.Do();
*/
}
6、享元模式
场景:
有多个需要复用的对象,且需要的状态一致。
定义:
共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
目的:
减少需要创建的对象数量。
缺点:
增加新的享元角色可能需要修改享元工厂类的源代码,违背了开闭原则。
代码示例:
/// <summary>
/// 享元模式
/// </summary>
public class Flyweight
{
/// <summary>
/// 文本打印对象
/// </summary>
/// <remarks>
/// 非享元角色
/// </remarks>
public class TextPrint
{
public TextPrint()
{
this.Text = String.Empty;
}
/// <summary>
/// 文本内容
/// </summary>
private string Text { get; set; }
/// <summary>
/// 添加文本
/// </summary>
/// <param name="text">添加的文本</param>
public void AddText(string text)
{
this.Text += text;
}
/// <summary>
/// 打印文本内容
/// </summary>
public void Print()
{
Console.WriteLine(Text);
}
}
/// <summary>
/// 文本写入享元抽象
/// </summary>
/// <remarks>抽象享元角色</remarks>
public interface TextWriteFlyweight
{
public void Write(TextPrint textPrint, string name);
}
/// <summary>
/// 食物文本写入角色
/// </summary>
/// <remarks>具体享元角色</remarks>
public class FoodTextWrite : TextWriteFlyweight
{
public void Write(TextPrint textPrint, string name)
{
textPrint.AddText($"Food:{name}");
}
}
/// <summary>
/// 饮品文本写入角色
/// </summary>
/// <remarks>具体享元角色</remarks>
public class DrinkTextWrite : TextWriteFlyweight
{
public void Write(TextPrint textPrint, string name)
{
textPrint.AddText($"Drink:{name}");
}
}
/// <summary>
/// 文本写入享元工厂
/// </summary>
public class TextWriteFlyweightFactory
{
/// <summary>
/// 文本写入享元字典
/// </summary>
private Dictionary<string, TextWriteFlyweight> TextWrites = new Dictionary<string, TextWriteFlyweight>();
/// <summary>
/// 获取文本写入享元对象
/// </summary>
/// <param name="type">类型标识</param>
/// <returns></returns>
public TextWriteFlyweight GetTextWriteFlyweight(string type)
{
if (TextWrites.ContainsKey(type))
{
//享元角色已存在,使用现有享元角色
return TextWrites[type];
}
else
{
//享元角色不存在,使用工厂模式创建角色
TextWriteFlyweight flyweight;
switch (type)
{
case "food":
flyweight = new FoodTextWrite();
break;
case "drink":
flyweight = new DrinkTextWrite();
break;
default:
throw new ArgumentException("type is invalid");
}
TextWrites.Add(type, flyweight);
return flyweight;
}
}
/*
调用方式:
TextPrint textPrint = new TextPrint();
TextWriteFlyweightFactory factory = new TextWriteFlyweightFactory();
var foodFlyweight = factory.GetTextWriteFlyweight("food");
var drinkFlyweight = factory.GetTextWriteFlyweight("drink");
foodFlyweight.Write(textPrint, "AAA");
drinkFlyweight.Write(textPrint, "BBB");
textPrint.Print();
*/
}
}
7、组合模式
场景:
由多个对象组成的树状结构有统一的操作。
定义:
将对象组合成树状的层次结构的模式,使用户对单个对象和组合对象具有一致的抽象。
目的:
可以一致的处理单个对象和组合对象。
加入新对象对象时无需修改代码,满足开闭原则。
代码示例:
/// <summary>
/// 组合模式
/// </summary>
public class Composite
{
/// <summary>
/// 文本打印
/// </summary>
/// <remarks>透明式抽象构建</remarks>
public interface TextPrint
{
//在安全式组合模式中,仅保留公有的方法(如Print)
/// <summary>
/// 添加子构件
/// </summary>
public void Add(TextPrint textPrint);
/// <summary>
/// 打印
/// </summary>
public void Print();
}
/// <summary>
/// 食物文本打印
/// </summary>
/// <remarks>树叶构件</remarks>
public class FoodTextPrint : TextPrint
{
public FoodTextPrint(string name)
{
this.Name = name;
}
/// <summary>
/// 食物名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 无Add操作,省略
/// </summary>
public void Add(TextPrint textPrint)
{
//无Add操作,省略
}
/// <summary>
/// 食物文本打印
/// </summary>
public void Print()
{
Console.WriteLine($"Food:{this.Name}");
}
}
/// <summary>
/// 文本打印组合
/// </summary>
/// <remarks>树枝构件</remarks>
public class TextPrintGroup : TextPrint
{
private List<TextPrint> TextPrints = new List<TextPrint>();
/// <summary>
/// 添加子构件
/// </summary>
/// <param name="textPrint">子构件</param>
public void Add(TextPrint textPrint)
{
TextPrints.Add(textPrint);
}
/// <summary>
/// 子构件文本打印
/// </summary>
public void Print()
{
foreach (TextPrint textPrint in TextPrints)
{
textPrint.Print();
}
}
}
/*
调用方式:
TextPrint group = new TextPrintGroup();
TextPrint group1 = new TextPrintGroup();
FoodTextPrint foodPrint = new FoodTextPrint("apple");
FoodTextPrint orangePrint = new FoodTextPrint("orange");
FoodTextPrint bananaPrint = new FoodTextPrint("banana");
//进行组合
group.Add(foodPrint);
group.Add(orangePrint);
group1.Add(bananaPrint);
group1.Add(group);
//不同组合的打印
group1.Print();
group.Print();
*/
}
配套源码:
C# .Net设计模式与代码实现