资源
设计模式 | 菜鸟教程 这个教程使用 Java 写的,但是我并没有系统性地学过 Java,真是太不幸运了!所以我决定用 C# 重写一遍。
C#
配置
众所周知,VSC 是世界上最好的 IDE……
VSC 中安装完 C#
、C# Extensions
插件后,在一个空项目中创建脚手架:
编写完代码后按 F5
进入调试模式。
C# 一些特性
abstract
:用于在基类中定义没有实现的方法,要求子类必须实现它。
override
:用于在子类中重写基类中已经实现的方法,提供不同的实现。
interface
:是一种定义契约的机制,它指定了实现类必须遵循的一组方法、属性、事件和索引器的签名,但不提供具体的实现。
面向对象编程
封装、继承和多态是面向对象编程(OOP)的三大核心概念,通常用于设计和实现更灵活、可维护的代码。
封装(Encapsulation)
封装是将数据(属性)和操作数据的方法(函数)捆绑在一起,并对外隐藏内部实现细节。外界只能通过公共接口访问对象的状态,而不能直接修改对象的内部数据。
目的是保护对象的内部数据不被外界随意修改,确保对象的状态始终合法。
例如,定义一个类 Car
,其中有一个私有属性 speed
,并通过公共方法 accelerate()
和 brake()
来操作该属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Car { private int speed; public void Accelerate () { speed += 10 ; } public int GetSpeed () { return speed; } }
继承(Inheritance)
继承是从现有类创建新类的机制,新类称为子类,现有类称为父类。子类继承了父类的属性和方法,可以增加新的功能或者重写父类的功能。
继承有助于代码的复用,避免重复定义相同的功能。
例如,Car
类可以继承自 Vehicle
类,Vehicle
定义了一些通用的属性和方法,而 Car
可以扩展或修改这些功能。
1 2 3 4 5 6 7 8 9 10 public class Vehicle { public int speed; public void Move () { Console.WriteLine("Vehicle is moving" ); } }public class Car : Vehicle { public void Horn () { Console.WriteLine("Car is honking" ); } }
多态(Polymorphism)
多态是指相同的操作作用于不同的对象上时,表现出不同的行为。多态分为编译时多态 (方法重载)和运行时多态 (方法重写)。
通过多态,子类可以替代父类,执行不同的实现,从而提高灵活性和可扩展性。
例如,Car
类和 Truck
类可以都有一个 Move()
方法,但它们可以有不同的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class Vehicle { public virtual void Move () { Console.WriteLine("Vehicle is moving" ); } }public class Car : Vehicle { public override void Move () { Console.WriteLine("Car is moving" ); } }public class Truck : Vehicle { public override void Move () { Console.WriteLine("Truck is moving" ); } } Vehicle myVehicle = new Car(); myVehicle.Move();
总结
封装 保护对象的内部数据,通过提供公共接口来操作数据。
继承 允许新类复用现有类的属性和方法,促进代码复用。
多态 使得相同的操作在不同的对象上产生不同的行为,提高代码的灵活性。
正文
设计模式的类型
根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:
创建型模式(Creational Patterns)
工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
Note
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
结构型模式(Structural Patterns)
适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
过滤器模式(Filter、Criteria Pattern)
组合模式(Composite Pattern)
装饰器模式(Decorator Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
Note
这些模式关注对象之间的组合和关系,旨在解决如何构建灵活且可复用的类和对象结构。
行为型模式(Behavioral Patterns)
责任链模式(Chain of Responsibility Pattern)
命令模式(Command Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
观察者模式(Observer Pattern)
状态模式(State Pattern)
空对象模式(Null Object Pattern)
策略模式(Strategy Pattern)
模板模式(Template Pattern)
访问者模式(Visitor Pattern)
Note
这些模式关注对象之间的通信和交互,旨在解决对象之间的责任分配和算法的封装。
设计模式的六大原则
1. 单一职责原则(SRP)
Note
单一职责原则要求一个类只负责一个功能。如果一个类承担了多个职责,它应该被拆分为多个类。
2. 开放-封闭原则(OCP)
Note
开放-封闭原则要求对扩展开放 ,对修改封闭 。我们可以通过继承或者接口来实现这个原则。
classDiagram
IShape <|-- Circle
IShape <|-- Rectangle
AreaCalculator --> IShape
class IShape {
<>
+double CalculateArea()
}
class Circle {
-double Radius
+double CalculateArea()
}
class Rectangle {
-double Width
-double Height
+double CalculateArea()
}
class AreaCalculator {
+double CalculateArea(IShape shape)
}
反例 正例
下面的例子违反了 OCP 原则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class AreaCalculator { public double CalculateArea (object shape ) { if (shape is Circle) { Circle circle = (Circle)shape; return Math.PI * circle.Radius * circle.Radius; } else if (shape is Rectangle) { Rectangle rectangle = (Rectangle)shape; return rectangle.Width * rectangle.Height; } return 0 ; } }
修改后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public interface IShape { double CalculateArea () ; }public class Circle : IShape { public double Radius { get ; set ; } public double CalculateArea () { return Math.PI * Radius * Radius; } }public class Rectangle : IShape { public double Width { get ; set ; } public double Height { get ; set ; } public double CalculateArea () { return Width * Height; } }public class AreaCalculator { public double CalculateArea (IShape shape ) { return shape.CalculateArea(); } }
这样,新增形状(如三角形)时只需实现 IShape
接口,无需修改 AreaCalculator
。
使用:
1 2 3 4 5 6 7 8 Circle circle = new Circle(); circle.Radius = 5 ; Rectangle rectangle = new Rectangle(); rectangle.Width = 10 ; rectangle.Height = 20 ; AreaCalculator calculator = new AreaCalculator(); Console.WriteLine("Circle area: " + calculator.CalculateArea(circle)); Console.WriteLine("Rectangle area: " + calculator.CalculateArea(rectangle));
1 2 Circle area: 78.53981633974483 Rectangle area: 200
3. 里氏替换原则(LSP)
Note
子类应该能够替代父类,而不会影响程序的正确性。
classDiagram
Shape <|-- Rectangle
Shape <|-- Square
class Shape {
<>
+abstract double Area()
}
class Rectangle {
-double Width
-double Height
+double Area()
}
class Square {
-double Side
+double Area()
}
反例 正例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Rectangle { public virtual double Width { get ; set ; } public virtual double Height { get ; set ; } public double Area () { return Width * Height; } }public class Square : Rectangle { public override double Width { set { base .Width = base .Height = value ; } } public override double Height { set { base .Width = base .Height = value ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public abstract class Shape { public abstract double Area () ; }public class Rectangle : Shape { public double Width { get ; set ; } public double Height { get ; set ; } public override double Area () { return Width * Height; } }public class Square : Shape { public double Side { get ; set ; } public override double Area () { return Side * Side; } }
通过抽象类 Shape
,矩形和正方形成为独立的类,避免了继承引发的问题。
4. 接口隔离原则(ISP)
Note
接口应该只包含客户端需要的方法,不应该强迫实现不必要的功能。
classDiagram
IPrintable <|.. BasicPrinter
IPrintable <|.. AdvancedPrinter
IScannable <|.. AdvancedPrinter
IFaxable <|.. AdvancedPrinter
class IPrintable {
<>
+void Print()
}
class IScannable {
<>
+void Scan()
}
class IFaxable {
<>
+void Fax()
}
class BasicPrinter {
+void Print()
}
class AdvancedPrinter {
+void Print()
+void Scan()
+void Fax()
}
反例 正例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface IPrinter { void Print () ; void Scan () ; void Fax () ; }public class BasicPrinter : IPrinter { public void Print () { Console.WriteLine("Printing..." ); } public void Scan () { throw new NotImplementedException(); } public void Fax () { throw new NotImplementedException(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public interface IPrintable { void Print () ; }public interface IScannable { void Scan () ; }public interface IFaxable { void Fax () ; }public class BasicPrinter : IPrintable { public void Print () { Console.WriteLine("Printing..." ); } }public class AdvancedPrinter : IPrintable , IScannable , IFaxable { public void Print () { Console.WriteLine("Printing..." ); } public void Scan () { Console.WriteLine("Scanning..." ); } public void Fax () { Console.WriteLine("Faxing..." ); } }
5. 依赖倒转原则(DIP)
Note
高层模块不应依赖低层模块,两者都应依赖抽象。
classDiagram
Application --> FileReader
class FileReader {
+string Read()
}
class Application {
-FileReader _fileReader
+void Start()
}
反例 正例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class FileReader { public string Read () { return "Reading from file." ; } }public class Application { private FileReader _fileReader; public Application () { _fileReader = new FileReader(); } public void Start () { Console.WriteLine(_fileReader.Read()); } }
classDiagram
IReader <|.. FileReader
IReader <|.. DatabaseReader
Application --> IReader
class IReader {
<>
+string Read()
}
class FileReader {
+string Read()
}
class DatabaseReader {
+string Read()
}
class Application {
-IReader _reader
+void Start()
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public interface IReader { string Read () ; }public class FileReader : IReader { public string Read () { return "Reading from file." ; } }public class DatabaseReader : IReader { public string Read () { return "Reading from database." ; } }public class Application { private readonly IReader _reader; public Application (IReader reader ) { _reader = reader; } public void Start () { Console.WriteLine(_reader.Read()); } }
1 2 3 4 IReader reader = new FileReader(); Application app = new Application(reader); app.Start();
6. 合成复用原则(CRP)
classDiagram
Car --> Engine
class Engine {
+void Start()
}
class Car {
-Engine _engine
+void Start()
+void Drive()
}
反例 正例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Engine { public void Start () { Console.WriteLine("Engine starts" ); } }public class Car : Engine { public void Drive () { Console.WriteLine("Car is driving" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Engine { public void Start () { Console.WriteLine("Engine starts" ); } }public class Car { private readonly Engine _engine; public Car (Engine engine ) { _engine = engine; } public void Start () { _engine.Start(); } public void Drive () { Console.WriteLine("Car is driving" ); } }
1 2 3 4 5 Engine engine = new Engine(); Car car = new Car(engine); car.Start(); car.Drive();
结构型模式(5)
工厂模式(Factory Pattern)
Note
工厂模式(Factory Pattern)提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。
应用实例
汽车制造 :你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
Hibernate :更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。
优点:
调用者只需要知道对象的名称即可创建对象。
扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
屏蔽了产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。
classDiagram
Shape <|.. Rectangle
Shape <|.. Square
Shape <|.. Circle
ShapeFactory --> Shape
class Shape {
<>
+void Draw()
}
class Rectangle {
+void Draw()
}
class Square {
+void Draw()
}
class Circle {
+void Draw()
}
class ShapeFactory {
+Shape GetShape(string shapeType)
}
说明 :
接口 Shape
:定义了一个 Draw()
方法,所有实现该接口的类都需要提供 Draw()
方法的实现。
Rectangle
、Square
、Circle
:分别是 Shape
接口的实现类,每个类都实现了 Draw()
方法,输出各自的形状信息。
ShapeFactory
:工厂类,根据传入的 shapeType
字符串创建并返回相应的形状对象(Rectangle
、Square
或 Circle
)。
FactoryPattenDemo
:演示类,包含 Main
方法,创建 ShapeFactory
实例并使用其方法生成形状对象,最后调用 Draw()
方法输出信息。
类之间的关系 :
Shape <|.. Rectangle
, Shape <|.. Square
, Shape <|.. Circle
表示 Rectangle
、Square
和 Circle
都实现了 Shape
接口。
ShapeFactory --> Shape
表示 ShapeFactory
依赖于 Shape
类型,并通过 GetShape
方法返回相应的实现类。
接口 接口实体类 工厂 使用
1 2 3 public interface Shape { void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Rectangle : Shape { public void Draw () { Console.WriteLine("Inside Rectangle::Draw() method." ); } }public class Square : Shape { public void Draw () { Console.WriteLine("Inside Square::Draw() method." ); } }public class Circle : Shape { public void Draw () { Console.WriteLine("Inside Circle::Draw() method." ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ShapeFactory { public Shape GetShape (string shapeType ) { if (shapeType.ToLower() == "rectangle" ) { return new Rectangle(); } else if (shapeType.ToLower() == "square" ) { return new Square(); } else if (shapeType.ToLower() == "circle" ) { return new Circle(); } else { return null ; } } }
1 2 3 4 5 6 7 8 9 public static void Main (string [] args ) { ShapeFactory shapeFactory = new ShapeFactory(); Shape shape1 = shapeFactory.GetShape("Rectangle" ); shape1.Draw(); Shape shape2 = shapeFactory.GetShape("Square" ); shape2.Draw(); Shape shape3 = shapeFactory.GetShape("Circle" ); shape3.Draw(); }
1 2 3 Inside Rectangle::Draw() method. Inside Square::Draw() method. Inside Circle::Draw() method.
抽象工厂模式(Abstract Factory Pattern)
Note
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
应用实例
汽车制造 :你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
Hibernate :更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。
优点
调用者只需要知道对象的名称即可创建对象。
扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
屏蔽了产品的具体实现,调用者只关心产品的接口。
缺点
每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。(emmm 所以我觉得这个有点蠢)
classDiagram
Shape <|.. Rectangle
Shape <|.. Square
Shape <|.. Circle
Color <|.. Red
Color <|.. Green
Color <|.. Blue
AbstractFactory <|-- ShapeFactory
AbstractFactory <|-- ColorFactory
FactoryProducer --> AbstractFactory
ShapeFactory --> Shape
ColorFactory --> Color
class Shape {
<>
+void Draw()
}
class Rectangle {
+void Draw()
}
class Square {
+void Draw()
}
class Circle {
+void Draw()
}
class Color {
<>
+void Fill()
}
class Red {
+void Fill()
}
class Green {
+void Fill()
}
class Blue {
+void Fill()
}
class AbstractFactory {
<>
+Shape GetShape(string shapeType)
+Color GetColor(string colorType)
}
class ShapeFactory {
+Shape GetShape(string shapeType)
+Color GetColor(string colorType)
}
class ColorFactory {
+Shape GetShape(string shapeType)
+Color GetColor(string colorType)
}
class FactoryProducer {
+static AbstractFactory GetFactory(string choice)
}
说明 :
Shape
和 Color
接口 :
Shape
接口定义了 Draw()
方法,所有实现该接口的类需要提供该方法的具体实现。
Color
接口定义了 Fill()
方法,所有实现该接口的类需要提供该方法的具体实现。
Rectangle
、Square
、Circle
类 :
这些类实现了 Shape
接口,并提供了 Draw()
方法的具体实现。
Red
、Green
、Blue
类 :
这些类实现了 Color
接口,并提供了 Fill()
方法的具体实现。
AbstractFactory
抽象类 :
定义了两个抽象方法 GetShape()
和 GetColor()
,分别用于获取形状和颜色对象。
ShapeFactory
和 ColorFactory
类 :
这些类继承自 AbstractFactory
,并分别实现了 GetShape()
和 GetColor()
方法。ShapeFactory
负责创建形状对象,ColorFactory
负责创建颜色对象。
FactoryProducer
类 :
这是一个工厂生产者类,根据传入的选择字符串返回一个相应的工厂实例(ShapeFactory
或 ColorFactory
)。
类之间的关系 :
Shape <|.. Rectangle
, Shape <|.. Square
, Shape <|.. Circle
表示 Rectangle
、Square
和 Circle
都实现了 Shape
接口。
Color <|.. Red
, Color <|.. Green
, Color <|.. Blue
表示 Red
、Green
和 Blue
都实现了 Color
接口。
AbstractFactory <|-- ShapeFactory
和 AbstractFactory <|-- ColorFactory
表示 ShapeFactory
和 ColorFactory
类继承自 AbstractFactory
。
FactoryProducer --> AbstractFactory
表示 FactoryProducer
类依赖于 AbstractFactory
,并通过 GetFactory()
方法返回一个相应的工厂实例。
形状接口 形状接口实体类 颜色接口 颜色接口实体类 抽象工厂 形状工厂 颜色工厂 工厂创造器/生成器 使用
1 2 3 4 public interface Shape { void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Rectangle : Shape { public void Draw () { Console.WriteLine("Inside Rectangle::Draw() method." ); } }public class Square : Shape { public void Draw () { Console.WriteLine("Inside Square::Draw() method." ); } }public class Circle : Shape { public void Draw () { Console.WriteLine("Inside Circle::Draw() method." ); } }
1 2 3 4 public interface Color { void Fill () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Red : Color { public void Fill () { Console.WriteLine("Inside Red::Fill() method." ); } }public class Green : Color { public void Fill () { Console.WriteLine("Inside Green::Fill() method." ); } }public class Blue : Color { public void Fill () { Console.WriteLine("Inside Blue::Fill() method." ); } }
1 2 3 4 public abstract class AbstractFactory { public abstract Shape GetShape (string shapeType ) ; public abstract Color GetColor (string colorType ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class ShapeFactory : AbstractFactory { public override Shape GetShape (string shapeType ) { if (shapeType.Equals("Rectangle" )) { return new Rectangle(); } else if (shapeType.Equals("Square" )) { return new Square(); } else if (shapeType.Equals("Circle" )) { return new Circle(); } return null ; } public override Color GetColor (string colorType ) { return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ColorFactory : AbstractFactory { public override Shape GetShape (string shapeType ) { return null ; } public override Color GetColor (string colorType ) { if (colorType.Equals("Red" )) { return new Red(); } else if (colorType.Equals("Green" )) { return new Green(); } else if (colorType.Equals("Blue" )) { return new Blue(); } return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class FactoryProducer { public static AbstractFactory GetFactory (string choice ) { if (choice.Equals("Shape" )) { return new ShapeFactory(); } else if (choice.Equals("Color" )) { return new ColorFactory(); } return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void Main (string [] args ) { AbstractFactory shapeFactory = FactoryProducer.GetFactory("Shape" ); Shape shape1 = shapeFactory.GetShape("Circle" ); shape1.Draw(); Shape shape2 = shapeFactory.GetShape("Rectangle" ); shape2.Draw(); Shape shape3 = shapeFactory.GetShape("Square" ); shape3.Draw(); AbstractFactory colorFactory = FactoryProducer.GetFactory("Color" ); Color color1 = colorFactory.GetColor("Red" ); color1.Fill(); Color color2 = colorFactory.GetColor("Green" ); color2.Fill(); Color color3 = colorFactory.GetColor("Blue" ); color3.Fill(); }
单例模式(Singleton Pattern)
Note
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。
注意:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
应用实例
一个班级只有一个班主任。
Windows 在多进程多线程环境下操作文件时,避免多个进程或线程同时操作一个文件,需要通过唯一实例进行处理。
设备管理器设计为单例模式,例如电脑有两台打印机,避免同时打印同一个文件。
优点
内存中只有一个实例,减少内存开销,尤其是频繁创建和销毁实例时(如管理学院首页页面缓存)。
避免资源的多重占用(如写文件操作)。
缺点
没有接口,不能继承。
与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心实例化方式。
classDiagram
SingleObject : -static SingleObject instance
SingleObject : -SingleObject()
SingleObject : +static SingleObject getInstance()
SingleObject : +void showMessage()
创建单例 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class SingleObject { public static SingleObject instance = new SingleObject(); private SingleObject () { } public static SingleObject getInstance () { return instance; } public void ShowMessage () { Console.WriteLine("Hello World!" ); } }
1 2 3 4 5 public static void Main (string [] args ) { SingleObject obj = SingleObject.getInstance(); obj.ShowMessage(); }
建造者模式(Builder Pattern)
Note
建造者模式是一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程与其表示相分离,从而可以创建具有不同表示形式的对象。
优点
分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
可以更好地控制构建过程,隐藏具体构建细节。
代码复用性高,可以在不同的构建过程中重复使用相同的建造者。
缺点
如果产品的属性较少,建造者模式可能会导致代码冗余。
增加了系统的类和对象数量。
classDiagram
Item <|.. Burger
Item <|.. ColdDrink
Packing <|.. Wrapper
Packing <|.. Bottle
Burger <|.. VegBurger
Burger <|.. ChickenBurger
ColdDrink <|.. Coke
ColdDrink <|.. Pepsi
Meal o-- Item
MealBuilder --> Meal
Item --> Packing
class Item {
<>
+string Name()
+Packing Packing()
+float Price()
}
class Packing {
<>
+string Pack()
}
class Wrapper {
+string Pack()
}
class Bottle {
+string Pack()
}
class Burger {
<>
+string Name()
+Packing Packing()
+float Price()
}
class ColdDrink {
<>
+string Name()
+Packing Packing()
+float Price()
}
class VegBurger {
+string Name()
+float Price()
}
class ChickenBurger {
+string Name()
+float Price()
}
class Coke {
+string Name()
+float Price()
}
class Pepsi {
+string Name()
+float Price()
}
class Meal {
-List- items
+void AddItem(Item item)
+float GetCost()
+void ShowItems()
}
class MealBuilder {
+Meal PrepareVegMeal()
+Meal PrepareNonVegMeal()
}
说明 :
Item
接口 :定义了商品的基本方法,包括 Name()
(名称)、Packing()
(包装方式)和 Price()
(价格)。
Packing
接口 :定义了 Pack()
方法,用于返回包装的形式(如 Wrapper
或 Bottle
)。
Wrapper
和 Bottle
:分别是 Packing
接口的实现类,提供具体的包装方式。
Burger
和 ColdDrink
抽象类:分别是 Item
的具体实现类,其中:
Burger
类定义了返回 Wrapper
作为包装方式,Name()
和 Price()
由子类实现。
ColdDrink
类定义了返回 Bottle
作为包装方式,Name()
和 Price()
由子类实现。
VegBurger
和 ChickenBurger
:分别是 Burger
的具体实现类,实现了 Name()
和 Price()
方法。
Coke
和 Pepsi
:分别是 ColdDrink
的具体实现类,实现了 Name()
和 Price()
方法。
Meal
类 :用于保存多个 Item
(如 VegBurger
、Coke
等),并提供 AddItem()
方法添加商品,GetCost()
方法计算总价,ShowItems()
方法展示所有商品的名称、包装和价格。
MealBuilder
类 :提供了两种餐点的构建方法:PrepareVegMeal()
和 PrepareNonVegMeal()
,分别用于构建素食餐和非素食餐。
类之间的关系 :
Item
接口由 Burger
和 ColdDrink
抽象类实现。
Packing
接口由 Wrapper
和 Bottle
类实现。
VegBurger
和 ChickenBurger
类继承自 Burger
,而 Coke
和 Pepsi
类继承自 ColdDrink
。
Meal
类包含多个 Item
对象,并提供方法来展示和计算餐点的总价。
MealBuilder
类负责创建具体的 Meal
实例。
食物条目和包装的接口 食物条目和包装的接口 创建实现 Item 接口的抽象类 创建扩展了 Burger 和 ColdDrink 的实体类 Meal 类 MealBuilder 类 使用
1 2 3 4 5 6 public interface Item { public string Name () ; public Packing Packing () ; public float Price () ; }
1 2 3 4 public interface Packing { public string Pack () ; }
1 2 3 4 5 6 7 public class Wrapper : Packing { public string Pack () { return "Wrapper" ; } }
1 2 3 4 5 6 7 public class Bottle : Packing { public string Pack () { return "Bottle" ; } }
1 2 3 4 5 6 7 8 9 10 11 public abstract class Burger : Item { public abstract string Name () ; public Packing Packing () { return new Wrapper(); } public abstract float Price () ; }
1 2 3 4 5 6 7 8 9 10 11 public abstract class ColdDrink : Item { public abstract string Name () ; public Packing Packing () { return new Bottle(); } public abstract float Price () ; }
1 2 3 4 5 6 7 8 9 10 11 12 public class VegBurger : Burger { public override string Name () { return "Veg Burger" ; } public override float Price () { return 25.0f ; } }
1 2 3 4 5 6 7 8 9 10 11 12 public class ChickenBurger : Burger { public override string Name () { return "Chicken Burger" ; } public override float Price () { return 50.5f ; } }
1 2 3 4 5 6 7 8 9 10 11 12 public class Coke : ColdDrink { public override float Price () { return 30.0f ; } public override string Name () { return "Coke" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Pepsi : ColdDrink { public override float Price () { return 35.0f ; } public override string Name () { return "Pepsi" ; } }
创建一个 Meal
类,带有上面定义的 Item
对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Meal { private List<Item> items = new List<Item>(); public void AddItem (Item item ) { items.Add(item); } public float GetCost () { float cost = 0 ; foreach (Item item in items) { cost += item.Price(); } return cost; } public void ShowItems () { foreach (Item item in items) { Console.WriteLine(item.Name() + " - " + item.Packing().Pack() + " - " + item.Price()); } } }
创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MealBuilder { public Meal PrepareVegMeal () { Meal meal = new Meal(); meal.AddItem(new VegBurger()); meal.AddItem(new Coke()); return meal; } public Meal PrepareNonVegMeal () { Meal meal = new Meal(); meal.AddItem(new ChickenBurger()); meal.AddItem(new Pepsi()); return meal; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void Main (string [] args ) { MealBuilder mealBuilder = new MealBuilder(); Meal vegMeal = mealBuilder.PrepareVegMeal(); Console.WriteLine("Veg Meal" ); vegMeal.ShowItems(); Console.WriteLine("Cost of Veg Meal: " + vegMeal.GetCost() + "\n" ); Meal nonVegMeal = mealBuilder.PrepareNonVegMeal(); Console.WriteLine("Non-Veg Meal" ); nonVegMeal.ShowItems(); Console.WriteLine("Cost of Non-Veg Meal: " + nonVegMeal.GetCost()); }
原型模式(Prototype Pattern)
Note
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。
它允许对象通过克隆的方式来创建副本,而不是通过构造器来实例化。
优点
缺点
配备克隆方法需要全面考虑类的功能,对已有类可能较难实现,特别是处理不支持串行化的间接对象或含有循环结构的引用时。
必须实现 Cloneable
接口。
classDiagram
Shape <|.. Rectangle
Shape <|.. Square
Shape <|.. Circle
ShapeCache --> Shape
class Shape {
<>
- string id
- string type
+ void Draw()
+ string GetType()
+ string GetId()
+ void SetId(string id)
+ object Clone()
}
class Rectangle {
+ void Draw()
}
class Square {
+ void Draw()
}
class Circle {
+ void Draw()
}
class ShapeCache {
+ static Dictionary shapeMap
+ static Shape GetShape(string shapeId)
+ static void LoadCache()
}
ShapeCache :一个缓存类,用来存储和克隆不同的形状对象。
ICloneable 接口的抽象类 抽象类的实体类 ShapeCache 类 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public abstract class Shape : ICloneable { private string id; protected string type; public abstract void Draw () ; public string GetType () { return type; } public string GetId () { return id; } public void SetId (string id ) { this .id = id; } public object Clone () { object clone = null ; try { clone = MemberwiseClone(); } catch (Exception e) { Console.WriteLine(e.Message); } return clone; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class Rectangle : Shape { public Rectangle () { type = "Rectangle" ; } public override void Draw () { Console.WriteLine("Inside Rectangle::Draw() method." ); } }public class Square : Shape { public Square () { type = "Square" ; } public override void Draw () { Console.WriteLine("Inside Square::Draw() method." ); } }public class Circle : Shape { public Circle () { type = "Circle" ; } public override void Draw () { Console.WriteLine("Inside Circle::Draw() method." ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class ShapeCache { private static Dictionary<string , Shape> shapeMap = new Dictionary<string , Shape>(); public static Shape GetShape (string shapeId ) { Shape cachedShape = shapeMap.GetValueOrDefault(shapeId); if (cachedShape != null ) { return (Shape)cachedShape.Clone(); } return null ; } public static void LoadCache () { Circle circle = new Circle(); circle.SetId("1" ); shapeMap[circle.GetId()] = circle; Square square = new Square(); square.SetId("2" ); shapeMap[square.GetId()] = square; Rectangle rectangle = new Rectangle(); rectangle.SetId("3" ); shapeMap[rectangle.GetId()] = rectangle; } }
1 2 3 4 5 6 7 8 9 10 11 12 public static void Main (string [] args ) { ShapeCache.LoadCache(); Shape shape1 = ShapeCache.GetShape("1" ); shape1.Draw(); Shape shape2 = ShapeCache.GetShape("2" ); shape2.Draw(); Shape shape3 = ShapeCache.GetShape("3" ); shape3.Draw(); }
结构型模式(8)
适配器模式(Adapter Pattern)
Note
适配器模式(Adapter Pattern)充当两个不兼容接口之间的桥梁,属于结构型设计模式。它通过一个中间件(适配器)将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作 。
优点
促进了类之间的协同工作,即使它们没有直接的关联。
提高了类的复用性。
增加了类的透明度。
提供了良好的灵活性。
缺点
过度使用适配器可能导致系统结构混乱,难以理解和维护。
在 Java 中,由于只能继承一个类,因此只能适配一个类,且目标类必须是抽象的(C++ 可以多继承,C# 可以用接口来实现多继承)。
结构
适配器模式包含以下几个主要角色:
目标接口(Target) :定义客户需要的接口。
适配者类(Adaptee) :定义一个已经存在的接口,这个接口需要适配。
适配器类(Adapter) :实现目标接口,并通过组合或继承的方式调用适配者类中的方法,从而实现目标接口。
classDiagram
class MediaPlayer {
+ void Play(string audioType, string fileName)
}
class AdvancedMediaPlayer {
+ void playVlc(string fileName)
+ void playMp4(string fileName)
}
class VlcPlayer {
+ void playVlc(string fileName)
+ void playMp4(string fileName)
}
class Mp4Player {
+ void playVlc(string fileName)
+ void playMp4(string fileName)
}
class MediaAdapter {
+ void Play(string audioType, string fileName)
- AdvancedMediaPlayer advancedMediaPlayer
}
class AudioPlayer {
+ void Play(string audioType, string fileName)
- MediaPlayer mediaPlayer
}
MediaPlayer <|.. AudioPlayer
AdvancedMediaPlayer <|.. VlcPlayer
AdvancedMediaPlayer <|.. Mp4Player
MediaPlayer <|.. MediaAdapter
MediaAdapter --> AdvancedMediaPlayer
MediaPlayer
接口 :定义了一个播放音频文件的 Play()
方法。
AdvancedMediaPlayer
接口 :定义了播放 vlc
和 mp4
格式音频文件的方法。
VlcPlayer
和 Mp4Player
:实现了 AdvancedMediaPlayer
接口,分别可以播放 vlc
和 mp4
格式的文件。
MediaAdapter
:适配器类,能将 MediaPlayer
接口的请求转换为 AdvancedMediaPlayer
接口的方法调用,从而使得 AudioPlayer
可以播放 vlc
和 mp4
格式的文件。
AudioPlayer
:客户端类,负责播放 mp3
文件,且通过 MediaAdapter
支持播放 vlc
和 mp4
格式文件。
创建接口 AdvancedMediaPlayer 接口的实体类 MediaPlayer 接口的适配器类 MediaPlayer 接口的实体类 使用
1 2 3 4 5 6 7 8 9 10 public interface MediaPlayer { public void Play (string audioType, string fileName ) ; }public interface AdvancedMediaPlayer { public void playVlc (string fileName ) ; public void playMp4 (string fileName ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class VlcPlayer : AdvancedMediaPlayer { public void playVlc (string fileName ) { Console.WriteLine("Playing VLC file: " + fileName); } public void playMp4 (string fileName ) { Console.WriteLine("Cannot play mp4 file with VLC player" ); } }public class Mp4Player : AdvancedMediaPlayer { public void playVlc (string fileName ) { Console.WriteLine("Cannot play vlc file with MP4 player" ); } public void playMp4 (string fileName ) { Console.WriteLine("Playing MP4 file: " + fileName); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class MediaAdapter : MediaPlayer { private AdvancedMediaPlayer advancedMediaPlayer; public MediaAdapter (string audioType ) { if (audioType.Equals("vlc" )) { advancedMediaPlayer = new VlcPlayer(); } else if (audioType.Equals("mp4" )) { advancedMediaPlayer = new Mp4Player(); } } public void Play (string audioType, string fileName ) { if (audioType.Equals("vlc" )) { advancedMediaPlayer.playVlc(fileName); } else if (audioType.Equals("mp4" )) { advancedMediaPlayer.playMp4(fileName); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class AudioPlayer : MediaPlayer { private MediaPlayer mediaPlayer; public void Play (string audioType, string fileName ) { if (audioType.Equals("mp3" )) { Console.WriteLine("Playing MP3 file: " + fileName); } else if (audioType.Equals("vlc" ) || audioType.Equals("mp4" )) { mediaPlayer = new MediaAdapter(audioType); mediaPlayer.Play(audioType, fileName); } else { Console.WriteLine("Invalid audio type" ); } } }
1 2 3 4 5 6 7 8 9 public static void Main (string [] args ) { AudioPlayer audioPlayer = new AudioPlayer(); audioPlayer.Play("mp3" , "beyond the horizon.mp3" ); audioPlayer.Play("mp4" , "alone.mp4" ); audioPlayer.Play("vlc" , "far far away.vlc" ); audioPlayer.Play("avi" , "mind me.avi" ); }
1 2 3 4 Playing MP3 file: beyond the horizon.mp3 Playing MP4 file: alone.mp4 Playing VLC file: far far away.vlc Invalid audio type
桥接模式(Bridge Pattern)
Note
桥接(Bridge)是用于把抽象化与实现化解耦 ,使得二者可以独立变化。
关键代码
抽象类 :定义一个抽象类,作为系统的一部分。
实现类 :定义一个或多个实现类,与抽象类通过聚合(而非继承)关联。
classDiagram
class DrawAPI {
+ void DrawCircle(int radius, int x, int y)
}
class RedCircle {
+ void DrawCircle(int radius, int x, int y)
}
class GreenCircle {
+ void DrawCircle(int radius, int x, int y)
}
class Shape {
<>
- DrawAPI drawAPI
+ Shape(DrawAPI drawAPI)
+ abstract void Draw()
}
class Circle {
- int radius
- int x
- int y
+ Circle(DrawAPI drawAPI, int radius, int x, int y)
+ void Draw()
}
DrawAPI <|.. RedCircle
DrawAPI <|.. GreenCircle
Shape <|.. Circle
Shape --> DrawAPI
DrawAPI
接口 :定义了具体绘制图形的方法(如绘制圆形)。它是实现部分的接口。
RedCircle
和 GreenCircle
类 :这两个类实现了 DrawAPI
接口,分别提供绘制红色和绿色圆形的具体实现。
Shape
抽象类 :通过持有一个 DrawAPI
对象,它将绘制的具体实现推迟到子类中,从而实现了绘制的抽象和实现分离。
Circle
类 :具体的形状类,继承自 Shape
,并通过 DrawAPI
来决定如何绘制圆形。
创建接口 桥接实现类 抽象类 Shape Shape 抽象类的实体类 使用
1 2 3 public interface DrawAPI { public void DrawCircle (int radius, int x, int y ) ; }
1 2 3 4 5 6 7 8 9 10 11 public class RedCircle : DrawAPI { public void DrawCircle (int radius, int x, int y ) { Console.WriteLine("Drawing a red circle of radius " + radius + " at (" + x + ", " + y + ")" ); } }public class GreenCircle : DrawAPI { public void DrawCircle (int radius, int x, int y ) { Console.WriteLine("Drawing a green circle of radius " + radius + " at (" + x + ", " + y + ")" ); } }
1 2 3 4 5 6 7 public abstract class Shape { protected DrawAPI drawAPI; public Shape (DrawAPI drawAPI ) { this .drawAPI = drawAPI; } public abstract void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Circle : Shape { private int radius; private int x; private int y; public Circle (DrawAPI drawAPI, int radius, int x, int y ) : base (drawAPI ) { this .radius = radius; this .x = x; this .y = y; } public override void Draw () { drawAPI.DrawCircle(radius, x, y); } }
1 2 3 4 5 6 7 public static void Main (string [] args ) { Shape redCircle = new Circle(new RedCircle(), 5 , 10 , 20 ); Shape greenCircle = new Circle(new GreenCircle(), 10 , 30 , 40 ); redCircle.Draw(); greenCircle.Draw(); }
1 2 Drawing a red circle of radius 5 at (10 , 20 ) Drawing a green circle of radius 10 at (30 , 40 )
过滤器模式(Filter Pattern)
Note
过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式 把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。
classDiagram
class Person {
- string name
- string gender
- string maritalStatus
+ Person(string name, string gender, string maritalStatus)
+ string GetName()
+ string GetGender()
+ string GetMaritalStatus()
}
class Criteria {
<>
+ List MeetCriteria(List persons)
}
class CriteriaMale {
+ List MeetCriteria(List persons)
}
class CriteriaFemale {
+ List MeetCriteria(List persons)
}
class CriteriaSingle {
+ List MeetCriteria(List persons)
}
class AndCriteria {
- Criteria criteria
- Criteria Othercriteria
+ AndCriteria(Criteria criteria, Criteria Othercriteria)
+ List MeetCriteria(List persons)
}
class OrCriteria {
- Criteria criteria
- Criteria Othercriteria
+ OrCriteria(Criteria criteria, Criteria Othercriteria)
+ List MeetCriteria(List persons)
}
Person --> Criteria
Criteria <|-- CriteriaMale
Criteria <|-- CriteriaFemale
Criteria <|-- CriteriaSingle
Criteria <|-- AndCriteria
Criteria <|-- OrCriteria
AndCriteria --> Criteria
OrCriteria --> Criteria
Person
类 :表示一个人的基本信息,包括姓名、性别和婚姻状况。提供了 getter 方法来获取这些信息。
Criteria
接口 :定义了筛选方法 MeetCriteria()
,所有具体的标准类都实现这个接口。
CriteriaMale
、CriteriaFemale
和 CriteriaSingle
类 :这些是具体的标准类,根据性别或婚姻状况来筛选 Person
对象。
AndCriteria
和 OrCriteria
类 :这两种类通过组合已有的标准(即通过 “与” 或 “或” 逻辑)来定义更复杂的筛选条件。
创建一个类 标准接口 实现了接口的实体类 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Person { private string name; private string gender; private string maritalStatus; public Person (string name, string gender, string maritalStatus ) { this .name = name; this .gender = gender; this .maritalStatus = maritalStatus; } public string GetName () { return name; } public string GetGender () { return gender; } public string GetMaritalStatus () { return maritalStatus; } }
1 2 3 4 public interface Criteria { public List<Person> MeetCriteria (List<Person> persons ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 public class CriteriaMale : Criteria { public List<Person> MeetCriteria (List<Person> persons ) { List<Person> malePersons = new List<Person>(); foreach (Person person in persons) { if (person.GetGender() == "Male" ) { malePersons.Add(person); } } return malePersons; } }public class CriteriaFemale : Criteria { public List<Person> MeetCriteria (List<Person> persons ) { List<Person> femalePersons = new List<Person>(); foreach (Person person in persons) { if (person.GetGender() == "Female" ) { femalePersons.Add(person); } } return femalePersons; } }public class CriteriaSingle : Criteria { public List<Person> MeetCriteria (List<Person> persons ) { List<Person> singlePersons = new List<Person>(); foreach (Person person in persons) { if (person.GetMaritalStatus() == "Single" ) { singlePersons.Add(person); } } return singlePersons; } }public class AndCriteria : Criteria { private Criteria criteria; private Criteria Othercriteria; public AndCriteria (Criteria criteria, Criteria Othercriteria ) { this .criteria = criteria; this .Othercriteria = Othercriteria; } public List<Person> MeetCriteria (List<Person> persons ) { List<Person> result = criteria.MeetCriteria(persons); result = Othercriteria.MeetCriteria(result); return result; } }public class OrCriteria : Criteria { private Criteria criteria; private Criteria Othercriteria; public OrCriteria (Criteria criteria, Criteria Othercriteria ) { this .criteria = criteria; this .Othercriteria = Othercriteria; } public List<Person> MeetCriteria (List<Person> persons ) { List<Person> result = criteria.MeetCriteria(persons); List<Person> otherResult = Othercriteria.MeetCriteria(persons); foreach (Person person in otherResult) { if (!result.Contains(person)) { result.Add(person); } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public static void Main (string [] args ) { List<Person> persons = [ new Person("John" , "Male" , "Single" ), new Person("Jane" , "Female" , "Married" ), new Person("Bob" , "Male" , "Single" ), new Person("Alice" , "Female" , "Married" ), new Person("Tom" , "Male" , "Single" ), new Person("Lily" , "Female" , "Single" ), ]; Criteria criteriaMale = new CriteriaMale(); Criteria criteriaFemale = new CriteriaFemale(); Criteria criteriaSingle = new CriteriaSingle(); Criteria criteriaAndMale = new AndCriteria(criteriaMale, criteriaSingle); Criteria criteriaAndFemale = new AndCriteria(criteriaFemale, criteriaSingle); Criteria criteriaOrMale = new OrCriteria(criteriaMale, criteriaSingle); Criteria criteriaOrFemale = new OrCriteria(criteriaFemale, criteriaSingle); List<Person> maleSinglePersons = criteriaAndMale.MeetCriteria(persons); List<Person> femaleSinglePersons = criteriaAndFemale.MeetCriteria(persons); List<Person> maleOrSinglePersons = criteriaOrMale.MeetCriteria(persons); List<Person> femaleOrSinglePersons = criteriaOrFemale.MeetCriteria(persons); Console.WriteLine("Male and Single: " + maleSinglePersons.Count); Console.WriteLine("Female and Single: " + femaleSinglePersons.Count); Console.WriteLine("Male or Single: " + maleOrSinglePersons.Count); Console.WriteLine("Female or Single: " + femaleOrSinglePersons.Count); }
1 2 3 4 Male and Single: 3 Female and Single: 1 Male or Single: 4 Female or Single: 6
组合模式(Composite Pattern)
Note
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象 。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
> graph TD;
CEO[首席执行官 John Doe] --> headSales[销售总监 Jane Smith];
CEO --> headMarketing[市场总监 Bob Johnson];
headSales --> salesExecutive1[销售员工 David Kim];
headSales --> salesExecutive2[销售员工 Karen Lee];
headMarketing --> clerk1[市场员工 Sarah Lee];
headMarketing --> clerk2[市场员工 Tom Johnson];
classDiagram
class Employee {
- string name
- string dept
- int salary
- List subordinates
+ Employee(string name, string dept, int salary)
+ void Add(Employee emp)
+ void Remove(Employee emp)
+ List GetSubordinates()
+ string toString()
}
Employee --> Employee : "subordinates"
Employee 类 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class Employee { private string name; private string dept; private int salary; private List<Employee> subordinates; public Employee (string name, string dept, int salary ) { this .name = name; this .dept = dept; this .salary = salary; this .subordinates = new List<Employee>(); } public void Add (Employee emp ) { subordinates.Add(emp); } public void Remove (Employee emp ) { subordinates.Remove(emp); } public List<Employee> GetSubordinates () { return subordinates; } public string toString () { return "Name: " + name + ", Department: " + dept + ", Salary: " + salary; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public static void Main (string [] args ) { Employee CEO = new Employee("John Doe" , "CEO" , 50000 ); Employee headSales = new Employee("Jane Smith" , "Head Sales" , 40000 ); Employee headMarketing = new Employee("Bob Johnson" , "Head Marketing" , 30000 ); Employee clerk1 = new Employee("Sarah Lee" , "Marketing" , 25000 ); Employee clerk2 = new Employee("Tom Johnson" , "Sales" , 25000 ); Employee salesExecutive1 = new Employee("David Kim" , "Sales" , 20000 ); Employee salesExecutive2 = new Employee("Karen Lee" , "Sales" , 20000 ); CEO.Add(headSales); CEO.Add(headMarketing); headSales.Add(salesExecutive1); headSales.Add(salesExecutive2); headMarketing.Add(clerk1); headMarketing.Add(clerk2); Console.WriteLine(CEO.toString()); foreach (Employee emp in CEO.GetSubordinates()) { Console.WriteLine(emp.toString()); foreach (Employee subemp in emp.GetSubordinates()) { Console.WriteLine(subemp.toString()); } } }
装饰器模式(Decorator Pattern)
Note
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
classDiagram
class Shape {
+void Draw()
}
class Rectangle {
+void Draw()
}
class Circle {
+void Draw()
}
class ShapeDecorator {
-Shape decoratedShape
+ShapeDecorator(Shape decoratedShape)
+void Draw()
}
class RedShapeDecorator {
+RedShapeDecorator(Shape decoratedShape)
+void Draw()
}
Shape <|-- Rectangle
Shape <|-- Circle
Shape <|-- ShapeDecorator
ShapeDecorator <|-- RedShapeDecorator
创建一个接口 创建接口的实体类 创建接口的抽象装饰类 扩展 ShapeDecorator 类的实体装饰类 使用
1 2 3 public interface Shape { void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 public class Rectangle : Shape { public void Draw () { Console.WriteLine("Rectangle.Draw()" ); } }public class Circle : Shape { public void Draw () { Console.WriteLine("Circle.Draw()" ); } }
1 2 3 4 5 6 7 8 9 10 11 public abstract class ShapeDecorator : Shape { protected Shape decoratedShape; public ShapeDecorator (Shape decoratedShape ) { this .decoratedShape = decoratedShape; } public void Draw () { decoratedShape.Draw(); } }
1 2 3 4 5 6 7 8 9 public class RedShapeDecorator : ShapeDecorator { public RedShapeDecorator (Shape decoratedShape ) : base (decoratedShape ) { } public void Draw () { base .Draw(); Console.WriteLine("RedShapeDecorator.Draw()" ); } }
1 2 3 4 5 6 7 8 9 public static void Main (string [] args ) { Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); circle.Draw(); redCircle.Draw(); redRectangle.Draw(); }
1 2 3 Circle.Draw() Circle.Draw() Rectangle.Draw()
外观模式(Facade Pattern)
Note
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
应用实例
通过外观模式,可以简化对表示层、业务逻辑层和数据访问层的访问。
classDiagram
class Shape {
+void Draw()
}
class Rectangle {
+void Draw()
}
class Square {
+void Draw()
}
class Circle {
+void Draw()
}
class ShapeMaker {
-Shape circle
-Shape rectangle
-Shape square
+ShapeMaker()
+void DrawCircle()
+void DrawRectangle()
+void DrawSquare()
}
Shape <|-- Rectangle
Shape <|-- Square
Shape <|-- Circle
ShapeMaker o-- Shape : uses
创建一个接口 创建接口的实体类 创建外观类 使用
1 2 3 4 public interface Shape { void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Square : Shape { public void Draw () { Console.WriteLine("Square is being drawn" ); } }public class Circle : Shape { public void Draw () { Console.WriteLine("Circle is being drawn" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker () { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void DrawCircle () { circle.Draw(); } public void DrawRectangle () { rectangle.Draw(); } public void DrawSquare () { square.Draw(); } }
1 2 3 4 5 6 7 8 public static void Main (string [] args ) { ShapeMaker shapeMaker = new ShapeMaker(); shapeMaker.DrawCircle(); shapeMaker.DrawRectangle(); shapeMaker.DrawSquare(); }
享元模式(Flyweight Pattern)
Note
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
classDiagram
class Shape {
<>
+void Draw()
}
class Circle {
-string color
-int x
-int y
-int radius
+Circle(string color)
+void SetX(int x)
+void SetY(int y)
+void SetRadius(int radius)
+void Draw()
}
class ShapeFactory {
-Dictionary circleMap
+Shape GetCircle(string color)
}
Shape <|-- Circle
ShapeFactory o-- Circle : manages
创建一个接口 创建接口的实体类 创建一个工厂 使用工厂
1 2 3 4 public interface Shape { void Draw () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Circle : Shape { private string color; private int x; private int y; private int radius; public Circle (string color ) { this .color = color; } public void SetX (int x ) { this .x = x; } public void SetY (int y ) { this .y = y; } public void SetRadius (int radius ) { this .radius = radius; } public void Draw () { Console.WriteLine("Drawing Circle with color " + color + " at (" + x + ", " + y + ") with radius " + radius); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class ShapeFactory { private static readonly Dictionary<string , Shape> circleMap = new Dictionary<string , Shape>(); public static Shape GetCircle (string color ) { Circle circle = (Circle)circleMap.GetValueOrDefault(color); if (circle == null ) { circle = new Circle(color); circleMap[color] = circle; Console.WriteLine("Creating circle of color : " + color); } return circle; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private static readonly string [] colors = { "Red" , "Green" , "Blue" , "White" , "Black" };public static void Main (string [] args ) { for (int i = 0 ; i < 20 ; i++) { Circle circle = (Circle)ShapeFactory.GetCircle(GetRandColor()); circle.SetX(GetRandX()); circle.SetY(GetRandY()); circle.SetRadius(50 ); circle.Draw(); } }private static string GetRandColor () { Random rand = new Random(); return colors[rand.Next(colors.Length)]; }private static int GetRandX () { Random rand = new Random(); return (int )rand.Next(100 ); }private static int GetRandY () { Random rand = new Random(); return (int )rand.Next(100 ); }
代理模式(Proxy Pattern)
Note
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能,这种类型的设计模式属于结构型模式。
代理模式通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介,负责将客户端的请求转发给目标对象,同时可以在转发请求前后进行额外的处理。
classDiagram
class Image {
<>
+void Display()
}
class RealImage {
-string fileName
+RealImage(string fileName)
+void Display()
-void LoadFromDisk(string fileName)
}
class ProxyImage {
-string fileName
-RealImage realImage
+ProxyImage(string fileName)
+void Display()
}
Image <|-- RealImage
Image <|-- ProxyImage
创建一个接口 接口的实体类 使用
1 2 3 public interface Image { void Display () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class RealImage : Image { private string fileName; public RealImage (string fileName ) { this .fileName = fileName; LoadFromDisk(fileName); } public void Display () { Console.WriteLine("Displaying image: " + fileName); } private void LoadFromDisk (string fileName ) { Console.WriteLine("Loading image from disk: " + fileName); } }public class ProxyImage : Image { private string fileName; private RealImage realImage; public ProxyImage (string fileName ) { this .fileName = fileName; } public void Display () { if (realImage == null ) { realImage = new RealImage(fileName); } realImage.Display(); } }
1 2 3 4 5 6 7 public static void Main () { Image image = new ProxyImage("image.jpg" ); image.Display(); image.Display(); }
1 2 3 Loading image from disk: image.jpg Displaying image: image.jpg Displaying image: image.jpg
行为型模式(12)
责任链模式(Chain of Responsibility Pattern)
Note
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
意图
允许将请求沿着处理者链传递,直到请求被处理为止。每个处理对象(日志记录器)只关注处理自己能够处理的日志级别,无法处理的请求则传递给下一个处理对象。
classDiagram
class AbstractLogger {
+int INFO = 1
+int ERROR = 2
+int DEBUG = 3
+int level
+AbstractLogger nextLogger
+void SetNextLogger(AbstractLogger nextLogger)
+void LogMessage(int level, string message)
<>
}
class ConsoleLogger {
+ConsoleLogger(int level)
+void Write(string message)
}
class ErrorLogger {
+ErrorLogger(int level)
+void Write(string message)
}
class FileLogger {
+FileLogger(int level)
+void Write(string message)
}
AbstractLogger <|-- ConsoleLogger
AbstractLogger <|-- ErrorLogger
AbstractLogger <|-- FileLogger
抽象的记录器类 记录器类的实体类 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public abstract class AbstractLogger { public static int INFO = 1 ; public static int ERROR = 2 ; public static int DEBUG = 3 ; protected int level; protected AbstractLogger nextLogger; public void SetNextLogger (AbstractLogger nextLogger ) { this .nextLogger = nextLogger; } public void LogMessage (int level, string message ) { if (this .level <= level) { Write(message); } if (nextLogger != null ) { nextLogger.LogMessage(level, message); } } protected abstract void Write (string message ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ConsoleLogger : AbstractLogger { public ConsoleLogger (int level ) { this .level = level; } protected override void Write (string message ) { Console.WriteLine("Standard Console::Logger: " + message); } }public class ErrorLogger : AbstractLogger { public ErrorLogger (int level ) { this .level = level; } protected override void Write (string message ) { Console.Error.WriteLine("Error Console::Logger: " + message); } }public class FileLogger : AbstractLogger { public FileLogger (int level ) { this .level = level; } protected override void Write (string message ) { Console.WriteLine("File::Logger: " + message); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private static AbstractLogger GetChainOfLoggers () { AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR); AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG); AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO); errorLogger.SetNextLogger(fileLogger); fileLogger.SetNextLogger(consoleLogger); return errorLogger; }public static void Main () { AbstractLogger loggerChain = GetChainOfLoggers(); loggerChain.LogMessage(AbstractLogger.INFO, "This is an info message" ); loggerChain.LogMessage(AbstractLogger.DEBUG, "This is a debug message" ); loggerChain.LogMessage(AbstractLogger.ERROR, "This is an error message" ); }
1 2 3 4 5 6 Standard Console::Logger: This is an info message Error Console::Logger: This is a debug message File::Logger: This is a debug message Standard Console::Logger: This is a debug message Error Console::Logger: This is an error message Standard Console::Logger: This is an error message
graph TD
A[ErrorLogger] --> B[FileLogger]
B[FileLogger] --> C[ConsoleLogger]
命令模式(Command Pattern)
Note
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。
命令模式将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
classDiagram
class Order {
<>
+exeute()
}
class Stock {
-string name = "ABC"
-int quantity = 100
+Buy()
+Sell()
}
class BuyStock {
-Stock abcStock
+BuyStock(Stock abcStock)
+exeute()
}
class SellStock {
-Stock abcStock
+SellStock(Stock abcStock)
+exeute()
}
class Broker {
-List~Order~ orderList
+TakeOrder(Order order)
+PlaceOrder()
}
Order <|.. BuyStock
Order <|.. SellStock
Stock <.. BuyStock : uses
Stock <.. SellStock : uses
Broker o--> Order : manages
表达式接口 请求类 接口的实体类 命令调用类 使用
1 2 3 public interface Order { void exeute () ; }
1 2 3 4 5 6 7 8 9 10 public class Stock { private string name = "ABC" ; private int quantity = 100 ; public void Buy () { Console.WriteLine("Stock [ Name: " + name + " Quantity: " + quantity + " ] bought" ); } public void Sell () { Console.WriteLine("Stock [ Name: " + name + " Quantity: " + quantity + " ] sold" ); } }
1 2 3 4 5 6 7 8 9 public class BuyStock : Order { private Stock abcStock; public BuyStock (Stock abcStock ) { this .abcStock = abcStock; } public void exeute () { abcStock.Buy(); } }
1 2 3 4 5 6 7 8 9 10 public class SellStock : Order { private Stock abcStock; public SellStock (Stock abcStock ) { this .abcStock = abcStock; } public void exeute () { abcStock.Sell(); } }
1 2 3 4 5 6 7 8 9 10 11 12 public class Broker { private List<Order> orderList = new List<Order>(); public void TakeOrder (Order order ) { orderList.Add(order); } public void PlaceOrder () { foreach (Order order in orderList) { order.exeute(); } orderList.Clear(); } }
创建具体命令对象 (BuyStock
或 SellStock
)。
将命令传递给 Broker
的 TakeOrder
方法 。
调用 Broker
的 PlaceOrder
方法,按序执行命令 ,完成股票的买卖操作。
1 2 3 4 5 6 7 8 9 public static void Main () { Stock abcStock = new Stock(); BuyStock buyStockOrder = new BuyStock(abcStock); SellStock sellStockOrder = new SellStock(abcStock); Broker broker = new Broker(); broker.TakeOrder(buyStockOrder); broker.TakeOrder(sellStockOrder); broker.PlaceOrder(); }
1 2 Stock [ Name: ABC Quantity: 100 ] bought Stock [ Name: ABC Quantity: 100 ] sold
解释器模式(Interpreter Pattern)
Note
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。
解释器模式给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
这种模式被用在 SQL 解析、符号处理引擎等。
classDiagram
class Expression {
<>
+Interpret(string context) bool
}
class TerminalExpression {
-string data
+TerminalExpression(string data)
+Interpret(string context) bool
}
class OrExpression {
-Expression exp1
-Expression exp2
+OrExpression(Expression exp1, Expression exp2)
+Interpret(string context) bool
}
class AndExpression {
-Expression exp1
-Expression exp2
+AndExpression(Expression exp1, Expression exp2)
+Interpret(string context) bool
}
Expression <|.. TerminalExpression
Expression <|.. OrExpression
Expression <|.. AndExpression
OrExpression o--> Expression : uses
AndExpression o--> Expression : uses
表达式接口 接口的实体类 创建规则,并解析
1 2 3 public interface Expression { public bool Interpret (string context ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class TerminalExpression : Expression { private string data; public TerminalExpression (string data ) { this .data = data; } public bool Interpret (string context ) { return context.Contains(data); } }public class OrExpression : Expression { private Expression exp1, exp2; public OrExpression (Expression exp1, Expression exp2 ) { this .exp1 = exp1; this .exp2 = exp2; } public bool Interpret (string context ) { return exp1.Interpret(context) || exp2.Interpret(context); } }public class AndExpression : Expression { private Expression exp1, exp2; public AndExpression (Expression exp1, Expression exp2 ) { this .exp1 = exp1; this .exp2 = exp2; } public bool Interpret (string context ) { return exp1.Interpret(context) && exp2.Interpret(context); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static Expression GetMaleExpression () { Expression robert = new TerminalExpression("Robert" ); Expression john = new TerminalExpression("John" ); return new OrExpression(robert, john); }public static Expression GetMarriedWomanExpression () { Expression jane = new TerminalExpression("Jane" ); Expression married = new TerminalExpression("married" ); return new AndExpression(jane, married); }public static void Main () { Expression isMale = GetMaleExpression(); Expression isMarriedWoman = GetMarriedWomanExpression(); Console.WriteLine("John is male: " + isMale.Interpret("John" )); Console.WriteLine("Jane is married woman: " + isMarriedWoman.Interpret("Jane is married" )); }
1 2 John is male: True Jane is married woman: True
迭代器模式(Iterator Pattern)
Note
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
classDiagram
class Iterator {
<>
+HasNext() bool
+Next() object
}
class Container {
<>
+GetIterator() Iterator
}
class NameRepository {
+string[] names
+GetIterator() Iterator
}
class NameIterator {
-int index
-NameRepository repository
+HasNext() bool
+Next() object
}
Container <|.. NameRepository
Iterator <|.. NameIterator
NameRepository o--> NameIterator : creates
NameIterator --> NameRepository : uses
创建接口 创建接口的实体类 使用
1 2 3 4 5 6 7 8 9 public interface Iterator { public bool HasNext () ; public object Next () ; }public interface Container { public Iterator GetIterator () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class NameRepository : Container { public string [] names = { "John" , "Mary" , "Peter" , "David" }; public Iterator GetIterator () { return new NameIterator(this ); } private class NameIterator : Iterator { private int index = 0 ; private NameRepository repository; public NameIterator (NameRepository repository ) { this .repository = repository; } public bool HasNext () { return index < repository.names.Length; } public object Next () { if (HasNext()) { return repository.names[index++]; } return null ; } }
1 2 3 4 5 6 7 8 public static void Main () { NameRepository repository = new NameRepository(); Iterator iterator = repository.GetIterator(); while (iterator.HasNext()) { Console.WriteLine("Name: " + iterator.Next()); } }
1 2 3 4 Name: John Name: Mary Name: Peter Name: David
Note
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性,属于行为型模式。
中介者模式定义了一个中介对象来封装一系列对象之间的交互。中介者使各对象之间不需要显式地相互引用,从而使其耦合松散,且可以独立地改变它们之间的交互。
MVC 框架 :控制器(C)作为模型(M)和视图(V)的中介者。
classDiagram
class ChatRoom {
+ShowMessage(User user, string message)
}
class User {
-string name
+GetName() string
+SetName(string name)
+SendMessage(string message)
<> User(string name)
}
User --> ChatRoom : uses
备忘录模式(Memento Pattern)
Note
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象,备忘录模式属于行为型模式。
备忘录模式允许在不破坏封装性的前提下,捕获和恢复对象的内部状态。
应用实例
游戏存档 :保存游戏进度,允许玩家加载之前的存档。
Windows 中的 Ctrl + Z :实现撤销操作。
classDiagram
class Memento {
-string state
+GetState() string
}
class Originator {
-string state
+SetState(string state)
+GetState() string
+CreateMemento() Memento
+SetMemento(Memento memento)
}
class Caretaker {
-List~Memento~ mementosList
+Add(Memento state)
+Get(int index) Memento
}
Memento <-- Originator : creates
Memento <-- Caretaker : manages
Caretaker --> Originator : uses
Memento 类 Originator 类 CareTaker 类 使用
1 2 3 4 5 6 7 8 9 10 11 12 public class Memento { private string state; public Memento (string state ) { this .state = state; } public string GetState () { return state; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Originator { private string state; public void SetState (string state ) { this .state = state; } public string GetState () { return state; } public Memento CreateMemento () { return new Memento(state); } public void SetMemento (Memento memento ) { state = memento.GetState(); } }
1 2 3 4 5 6 7 8 9 10 11 12 public class Caretaker { private List<Memento> mementosList = new List<Memento>(); public void Add (Memento state ) { mementosList.Add(state); } public Memento Get (int index ) { return mementosList[index]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void Main () { Originator originator = new Originator(); Caretaker caretaker = new Caretaker(); originator.SetState("State 1" ); originator.SetState("State 2" ); caretaker.Add(originator.CreateMemento()); originator.SetState("State 3" ); caretaker.Add(originator.CreateMemento()); originator.SetState("State 4" ); caretaker.Add(originator.CreateMemento()); Console.WriteLine("Current state: " + originator.GetState()); originator.SetMemento(caretaker.Get(0 )); Console.WriteLine("First state: " + originator.GetState()); originator.SetMemento(caretaker.Get(1 )); Console.WriteLine("Second state: " + originator.GetState()); }
1 2 3 Current state: State 4 First state: State 2 Second state: State 3
观察者模式(Observer Pattern)
Note
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
classDiagram
class Subject {
-List~Observer~ observers
-int state
+GetState() int
+SetState(int state)
+Attach(Observer observer)
+Detach(Observer observer)
-NotifyObservers()
}
class Observer {
<>
#Subject subject
+Update()
}
Subject --> Observer : manages
class BinaryObserver {
+Update()
}
class OctalObserver {
+Update()
}
class HexObserver {
+Update()
}
Observer <|-- BinaryObserver
Observer <|-- OctalObserver
Observer <|-- HexObserver
Subject 类 Observer 类 实体观察者类 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Subject { private List<Observer> observers = new List<Observer>(); private int state; public int GetState () { return state; } public void SetState (int state ) { this .state = state; NotifyObservers(); } public void Attach (Observer observer ) { observers.Add(observer); } public void Detach (Observer observer ) { observers.Remove(observer); } private void NotifyObservers () { foreach (Observer observer in observers) { observer.Update(); } } }
1 2 3 4 5 public abstract class Observer { protected Subject subject; public abstract void Update () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class BinaryObserver : Observer { public BinaryObserver (Subject subject ) { this .subject = subject; this .subject.Attach(this ); } public override void Update () { Console.WriteLine("Binary string: " + Convert.ToString(subject.GetState(), 2 )); } }public class OctalObserver : Observer { public OctalObserver (Subject subject ) { this .subject = subject; this .subject.Attach(this ); } public override void Update () { Console.WriteLine("Octal string: " + Convert.ToString(subject.GetState(), 8 )); } }public class HexObserver : Observer { public HexObserver (Subject subject ) { this .subject = subject; this .subject.Attach(this ); } public override void Update () { Console.WriteLine("Hexadecimal string: " + Convert.ToString(subject.GetState(), 16 )); } }
1 2 3 4 5 6 7 8 9 public static void Main () { Subject subject = new Subject(); BinaryObserver binaryObserver = new BinaryObserver(subject); OctalObserver octalObserver = new OctalObserver(subject); HexObserver hexObserver = new HexObserver(subject); subject.SetState(10 ); subject.SetState(15 ); }
状态模式(State Pattern)
Note
在状态模式(State Pattern)中,类的行为是基于它的状态改变的 ,这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context
对象。
classDiagram
class Context {
-State state
+Context()
+SetState(State state)
+GetState() State
}
class State {
<>
+DoAction(Context context)
}
Context --> State : "has-a"
class StartState {
+DoAction(Context context)
+ToString() string
}
class StopState {
+DoAction(Context context)
+ToString() string
}
State <|.. StartState
State <|.. StopState
接口 接口的实体类 Context 类 使用
1 2 3 4 public interface State { public void DoAction (Context context ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class StartState : State { public void DoAction (Context context ) { Console.WriteLine("Starting the application" ); context.SetState(this ); } public override string ToString () { return "Start State" ; } }public class StopState : State { public void DoAction (Context context ) { Console.WriteLine("Stopping the application" ); context.SetState(this ); } public override string ToString () { return "Stop State" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Context { private State state; public Context () { state = null ; } public void SetState (State state ) { this .state = state; } public State GetState () { return state; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void Main () { Context context = new Context(); StartState startState = new StartState(); startState.DoAction(context); Console.WriteLine("Current state: " + context.GetState()); StopState stopState = new StopState(); stopState.DoAction(context); Console.WriteLine("Current state: " + context.GetState()); }
1 2 3 4 Starting the application Current state: Start State Stopping the application Current state: Stop State
空对象模式(Null Object Pattern)
Note
在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。
在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。
使用一个空对象代替 null
值,这个空对象实现了相同的接口,但对请求不做任何操作或提供默认操作。
classDiagram
class AbstractCustomer {
<>
- string name
+ IsNil() bool
+ GetName() string
}
AbstractCustomer <|-- RealCustomer
AbstractCustomer <|-- NilCustomer
class RealCustomer {
+ RealCustomer(string name)
+ IsNil() bool
+ GetName() string
}
class NilCustomer {
+ IsNil() bool
+ GetName() string
}
class CustomerFactory {
+ names : string[]
+ CreateCustomer(string name) AbstractCustomer
}
CustomerFactory ..> AbstractCustomer : depends
抽象类 实体类 CustomerFactory 类 使用
1 2 3 4 5 public abstract class AbstractCustomer { protected string name; public abstract bool IsNil () ; public abstract string GetName () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class RealCustomer : AbstractCustomer { public RealCustomer (string name ) { this .name = name; } public override bool IsNil () { return false ; } public override string GetName () { return name; } }public class NilCustomer : AbstractCustomer { public override bool IsNil () { return true ; } public override string GetName () { return "Not Available in Customer Database" ; } }
1 2 3 4 5 6 7 8 9 10 public class CustomerFactory { public static readonly string [] names = { "John" , "Mary" , "Tom" , "David" }; public static AbstractCustomer CreateCustomer (string name ) { if (Array.IndexOf(names, name) >= 0 ) { return new RealCustomer(name); } else { return new NilCustomer(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void Main () { AbstractCustomer customer1 = CustomerFactory.CreateCustomer("John" ); AbstractCustomer customer2 = CustomerFactory.CreateCustomer("Peter" ); AbstractCustomer customer3 = CustomerFactory.CreateCustomer("Mary" ); AbstractCustomer customer4 = CustomerFactory.CreateCustomer("Tom" ); Console.WriteLine("Customers:" ); Console.WriteLine(customer1.GetName()); Console.WriteLine(customer2.GetName()); Console.WriteLine(customer3.GetName()); Console.WriteLine(customer4.GetName()); }
1 2 3 4 5 Customers: John Not Available in Customer Database Mary Tom
策略模式(Strategy Pattern)
Note
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
**意图:**将每个算法封装起来,使它们可以互换使用。
classDiagram
class Strategy {
<>
+ DoOperation(int num1, int num2) int
}
class OperationAdd {
+ DoOperation(int num1, int num2) int
}
class OperationSubtract {
+ DoOperation(int num1, int num2) int
}
class OperationMultiply {
+ DoOperation(int num1, int num2) int
}
Strategy <|.. OperationAdd
Strategy <|.. OperationSubtract
Strategy <|.. OperationMultiply
class Context {
- Strategy strategy
+ Context(Strategy strategy)
+ DoOperation(int num1, int num2) int
}
Context --> Strategy
接口 接口的实体类 Context 类 使用
1 2 3 public interface Strategy { public int DoOperation (int num1, int num2 ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class OperationAdd : Strategy { public int DoOperation (int num1, int num2 ) { return num1 + num2; } }public class OperationSubtract : Strategy { public int DoOperation (int num1, int num2 ) { return num1 - num2; } }public class OperationMultiply : Strategy { public int DoOperation (int num1, int num2 ) { return num1 * num2; } }
1 2 3 4 5 6 7 8 9 public class Context { private Strategy strategy; public Context (Strategy strategy ) { this .strategy = strategy; } public int DoOperation (int num1, int num2 ) { return strategy.DoOperation(num1, num2); } }
1 2 3 4 5 6 7 8 9 10 11 public static void Main () { Context context = new Context(new OperationAdd()); Console.WriteLine("10 + 5 = " + context.DoOperation(10 , 5 )); context = new Context(new OperationSubtract()); Console.WriteLine("10 - 5 = " + context.DoOperation(10 , 5 )); context = new Context(new OperationMultiply()); Console.WriteLine("10 * 5 = " + context.DoOperation(10 , 5 )); }
模板模式(Template Pattern)
Note
模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板 。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
classDiagram
class Game {
<>
+ Initialize()
+ StartPlay()
+ EndPlay()
+ Play()
}
class Cricket {
+ Initialize()
+ StartPlay()
+ EndPlay()
}
class Football {
+ Initialize()
+ StartPlay()
+ EndPlay()
}
Game <|-- Cricket
Game <|-- Football
抽象类 抽象类的实体类 使用
1 2 3 4 5 6 7 8 9 10 public abstract class Game { public abstract void Initialize () ; public abstract void StartPlay () ; public abstract void EndPlay () ; public void Play () { Initialize(); StartPlay(); EndPlay(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Cricket : Game { public override void Initialize () { Console.WriteLine("Cricket game initialized." ); } public override void StartPlay () { Console.WriteLine("Cricket game started." ); } public override void EndPlay () { Console.WriteLine("Cricket game ended." ); } }public class Football : Game { public override void Initialize () { Console.WriteLine("Football game initialized." ); } public override void StartPlay () { Console.WriteLine("Football game started." ); } public override void EndPlay () { Console.WriteLine("Football game ended." ); } }
1 2 3 4 5 6 7 public static void Main () { Game game = new Cricket(); game.Play(); game = new Football(); game.Play(); }
1 2 3 4 5 6 Cricket game initialized. Cricket game started. Cricket game ended. Football game initialized. Football game started. Football game ended.
访问者模式(Visitor Pattern)
Note
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。
classDiagram
class ComputerPart {
<>
+ Accept(ComputerPartVisitor visitor)
}
class Keyboard {
+ Accept(ComputerPartVisitor visitor)
}
class Mouse {
+ Accept(ComputerPartVisitor visitor)
}
class Monitor {
+ Accept(ComputerPartVisitor visitor)
}
class Computer {
- ComputerPart[] parts
+ Accept(ComputerPartVisitor visitor)
}
class ComputerPartVisitor {
<>
+ Visit(Computer computer)
+ Visit(Keyboard keyboard)
+ Visit(Mouse mouse)
+ Visit(Monitor monitor)
}
class ComputerPartDisplayVisitor {
+ Visit(Computer computer)
+ Visit(Keyboard keyboard)
+ Visit(Mouse mouse)
+ Visit(Monitor monitor)
}
ComputerPart <|.. Keyboard
ComputerPart <|.. Mouse
ComputerPart <|.. Monitor
ComputerPart <|.. Computer
ComputerPartVisitor <|.. ComputerPartDisplayVisitor
Computer o-- ComputerPart
ComputerPart --> ComputerPartVisitor : Accept(visitor)
接口 接口的实体类 访问者的接口 类的实体访问者 使用
1 2 3 public interface ComputerPart { public void Accept (ComputerPartVisitor computerPartVisitor ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Keyboard : ComputerPart { public void Accept (ComputerPartVisitor computerPartVisitor ) { computerPartVisitor.Visit(this ); } }public class Mouse : ComputerPart { public void Accept (ComputerPartVisitor computerPartVisitor ) { computerPartVisitor.Visit(this ); } }public class Monitor : ComputerPart { public void Accept (ComputerPartVisitor computerPartVisitor ) { computerPartVisitor.Visit(this ); } }public class Computer : ComputerPart { ComputerPart[] parts; public Computer () { parts = [new Keyboard(), new Mouse(), new Monitor()]; } public void Accept (ComputerPartVisitor computerPartVisitor ) { foreach (ComputerPart part in parts) { part.Accept(computerPartVisitor); } } }
1 2 3 4 5 6 public interface ComputerPartVisitor { public void Visit (Computer computer ) ; public void Visit (Keyboard keyboard ) ; public void Visit (Mouse mouse ) ; public void Visit (Monitor monitor ) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ComputerPartDisplayVisitor : ComputerPartVisitor { public void Visit (Computer computer ) { Console.WriteLine("Displaying Computer" ); } public void Visit (Keyboard keyboard ) { Console.WriteLine("Displaying Keyboard" ); } public void Visit (Mouse mouse ) { Console.WriteLine("Displaying Mouse" ); } public void Visit (Monitor monitor ) { Console.WriteLine("Displaying Monitor" ); } }
1 2 3 4 5 public static void Main () { ComputerPart computer = new Computer(); computer.Accept(new ComputerPartDisplayVisitor()); }
1 2 3 Displaying Keyboard Displaying Mouse Displaying Monitor