0%

组合模式 - 结构型模式的层层叠加

在软件设计中,组合模式是一种结构型设计模式,它通过将对象组合成树状结构,以表示“部分-整体”的层次结构。本文将深入讨论组合模式的概念、实现方式以及在实际应用中的使用场景。

组合模式的概念

组合模式(Composite Pattern)是一种结构型设计模式,其核心思想是将对象组合成树状结构,以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地对待单个对象和组合对象。

组合模式的 UML 类图

classDiagram
    class Component {
        + Operation(): void
    }

    class Leaf {
        + Operation(): void
    }

    class Composite {
        + Add(component: Component): void
        + Remove(component: Component): void
        + Operation(): void
    }

    Component <|-- Leaf
    Component <|-- Composite

组合模式的实现方式

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
using System;
using System.Collections.Generic;

// 抽象组件类
public abstract class Component
{
public abstract void Operation();
}

// 叶子组件类
public class Leaf : Component
{
public override void Operation()
{
Console.WriteLine("Leaf Operation");
}
}

// 复合组件类
public class Composite : Component
{
private List<Component> children = new List<Component>();

public void Add(Component component)
{
children.Add(component);
}

public void Remove(Component component)
{
children.Remove(component);
}

public override void Operation()
{
Console.WriteLine("Composite Operation");

foreach (var child in children)
{
child.Operation();
}
}
}

组合模式的应用场景

组合模式适用于以下情况:

  1. 系统需要处理整体与部分的关系,希望客户端可以忽略单个对象与组合对象的差异。
  2. 系统中的对象可以形成树状结构,且客户端希望一致地对待所有对象。
  3. 希望在不同层次结构中使用相同的操作,而不用关心对象的具体类型。

组合模式的优势

  1. 简化客户端代码: 客户端无需区分处理单个对象和组合对象,统一了接口,简化了客户端代码。

  2. 灵活性和可扩展性: 组合模式使得系统具备灵活性和可扩展性,可以方便地添加新的叶子节点或者复合节点。

  3. 统一操作: 组合模式使得客户端可以统一地对待单个对象和组合对象,无需关心对象的具体类型。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Program
{
static void Main()
{
// 创建叶子对象
Leaf leaf1 = new Leaf();
Leaf leaf2 = new Leaf();

// 创建复合对象,并将叶子对象添加进去
Composite composite = new Composite();
composite.Add(leaf1);
composite.Add(leaf2);

// 调用复合对象的操作方法,实际上会递归调用叶子对象的操作方法
composite.Operation();
}
}

总结

组合模式是一种强大的结构型设计模式,通过将对象组合成树状结构,使得客户端可以统一地对待单个对象和组合对象。组合模式在处理整体与部分的关系、以及构建具有层次结构的对象时,能够提供简洁而灵活的解决方案。在实际应用中,组合模式需要注意递归调用的性能问题,确保在大规模树状结构中的性能表现。

装饰模式 - 结构型模式的灵活包装

在软件设计中,装饰模式是一种结构型设计模式,它允许在不改变对象接口的情况下,动态地将责任附加到对象上。本文将深入讨论装饰模式的概念、实现方式以及在实际应用中的使用场景。

装饰模式的概念

装饰模式(Decorator Pattern)是一种结构型设计模式,其核心思想是通过装饰器类包装原始类,以动态地扩展其功能,而无需修改原始类的接口。装饰模式是一种通过对象组合而非继承的方式,使得行为可以被灵活地扩展。

装饰模式的 UML 类图

classDiagram
    class Component {
        + Operation(): void
    }

    class ConcreteComponent {
        + Operation(): void
    }

    class Decorator {
        - component: Component
        + Operation(): void
    }

    class ConcreteDecoratorA {
        + Operation(): void
        + AddedBehavior(): void
    }

    class ConcreteDecoratorB {
        + Operation(): void
        + AddedBehavior(): void
    }

    Component <|.. ConcreteComponent
    Component <|.. Decorator
    Decorator <|-- ConcreteDecoratorA
    Decorator <|-- ConcreteDecoratorB

装饰模式的实现方式

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
using System;

// 抽象组件类
public abstract class Component
{
public abstract void Operation();
}

// 具体组件类
public class ConcreteComponent : Component
{
public override void Operation()
{
Console.WriteLine("Concrete Component Operation");
}
}

// 抽象装饰器类
public abstract class Decorator : Component
{
protected Component component;

public void SetComponent(Component component)
{
this.component = component;
}

public override void Operation()
{
if (component != null)
{
component.Operation();
}
}
}

// 具体装饰器类A
public class ConcreteDecoratorA : Decorator
{
public override void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("Concrete Decorator A Operation");
}

private void AddedBehavior()
{
Console.WriteLine("Added Behavior A");
}
}

// 具体装饰器类B
public class ConcreteDecoratorB : Decorator
{
public override void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("Concrete Decorator B Operation");
}

private void AddedBehavior()
{
Console.WriteLine("Added Behavior B");
}
}

装饰模式的应用场景

装饰模式适用于以下情况:

  1. 需要动态地给对象添加额外的职责,而且这些职责可以被多次叠加。
  2. 使用继承扩展功能不太灵活,希望通过组合来扩展对象功能。
  3. 需要扩展一些无法修改其源码的类的功能。

装饰模式的优势

  1. 灵活性高: 装饰模式通过对象组合的方式,使得可以动态地扩展对象的功能,而无需修改其接口。

  2. 遵循开闭原则: 装饰模式允许在不修改已有代码的情况下,引入新的装饰器类,符合开闭原则。

  3. 可组合性: 可以通过不同的装饰器类组合出多种不同的行为组合,使得系统更具弹性和可扩展性。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
{
static void Main()
{
// 创建具体组件对象
ConcreteComponent component = new ConcreteComponent();

// 创建具体装饰器对象A,并设置其包装的组件对象
ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
decoratorA.SetComponent(component);

// 创建具体装饰器对象B,并设置其包装的组件对象
ConcreteDecoratorB decoratorB = new ConcreteDecoratorB();
decoratorB.SetComponent(decoratorA);

// 调用装饰器对象的操作方法,实际上会动态调用所有包装的组件的操作方法
decoratorB.Operation();
}
}

总结

装饰模式是一种结构型设计模式,通过对象组合的方式,动态地扩

展对象的功能。装饰模式使得系统具备了更高的灵活性,能够在运行时动态地添加新的职责。在实际应用中,装饰模式常用于需要动态地扩展对象功能、而又不希望通过继承来实现的场景。

享元模式 - 结构型模式的轻量级共享

在软件设计中,享元模式是一种结构型设计模式,它通过共享对象来减小系统中对象的数量,从而提高系统的性能。本文将深入讨论享元模式的概念、实现方式以及在实际应用中的使用场景。

享元模式的概念

享元模式(Flyweight Pattern)是一种结构型设计模式,其核心思想是共享对象以减小系统中对象的数量。享元模式适用于大量相似对象的场景,通过共享内部状态,减小存储和对象创建的开销。

享元模式的 UML 类图

classDiagram
    class Flyweight {
        + Operation(state: int): void
    }

    class ConcreteFlyweight {
        + Operation(state: int): void
    }

    class UnsharedConcreteFlyweight {
        + Operation(state: int): void
    }

    class FlyweightFactory {
        - flyweights: Dictionary
        + GetFlyweight(key: int): Flyweight
    }

    Flyweight <|.. ConcreteFlyweight
    Flyweight <|.. UnsharedConcreteFlyweight
    FlyweightFactory --> Flyweight

享元模式的实现方式

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
using System;
using System.Collections.Generic;

// 抽象享元类
public abstract class Flyweight
{
public abstract void Operation(int state);
}

// 具体享元类
public class ConcreteFlyweight : Flyweight
{
public override void Operation(int state)
{
Console.WriteLine($"Concrete Flyweight Operation with state: {state}");
}
}

// 不共享的具体享元类
public class UnsharedConcreteFlyweight : Flyweight
{
public override void Operation(int state)
{
Console.WriteLine($"Unshared Concrete Flyweight Operation with state: {state}");
}
}

// 享元工厂类
public class FlyweightFactory
{
private Dictionary<int, Flyweight> flyweights = new Dictionary<int, Flyweight>();

public Flyweight GetFlyweight(int key)
{
if (flyweights.ContainsKey(key))
{
return flyweights[key];
}
else
{
Flyweight flyweight = new ConcreteFlyweight();
flyweights.Add(key, flyweight);
return flyweight;
}
}
}

享元模式的应用场景

享元模式适用于以下情况:

  1. 系统中存在大量相似对象,占用大量内存。
  2. 对象的状态可以外部状态和内部状态,外部状态可以在对象被创建后进行修改。
  3. 系统中的对象可以被共享,且客户端可以忽略对象的具体状态。

享元模式的优势

  1. 减小内存占用: 享元模式通过共享内部状态,减小系统中对象的数量,从而减小内存占用。
  2. 提高性能: 由于减少了对象的数量,系统性能得到提升,特别在需要大量创建相似对象的场景中。
  3. 灵活性: 享元模式将对象的状态分为内部状态和外部状态,外部状态可以在对象被创建后进行修改,提高了灵活性。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Program
{
static void Main()
{
// 创建享元工厂对象
FlyweightFactory factory = new FlyweightFactory();

// 获取共享的具体享元对象
Flyweight flyweight1 = factory.GetFlyweight(1);

// 调用具体享元对象的操作方法,实际上会共享相同的对象
flyweight1.Operation(10);

// 获取不共享的具体享元对象
Flyweight flyweight2 = new UnsharedConcreteFlyweight();

// 调用不共享的具体享元对象的操作方法
flyweight2.Operation(20);
}
}

总结

享元模式是一种结构型设计模式,通过共享内部状态以减小系统中对象的数量,提高系统性能。享元模式适用于大量相似对象的场景,通过共享内部状态,减小存储和对象创建的开销。在实际应用中,享元模式需要权衡共享状态和非共享状态的管理,确保系统的灵活性和可维护性。

外观模式 - 结构型模式的简化接口

在软件设计中,外观模式是一种结构型设计模式,它提供了一个统一的接口,用于访问系统中的一组接口。本文将深入讨论外观模式的概念、实现方式以及在实际应用中的使用场景。

外观模式的概念

外观模式(Facade Pattern)是一种结构型设计模式,其核心思想是提供一个简化的接口,用于访问系统中的一组接口。外观模式通过创建一个高层接口,将系统中的一组接口封装起来,使得客户端可以更容易地使用系统。

外观模式的 UML 类图

classDiagram
    class Facade {
        + Operation(): void
    }

    class SubsystemA {
        + OperationA(): void
    }

    class SubsystemB {
        + OperationB(): void
    }

    class SubsystemC {
        + OperationC(): void
    }

    Facade --> SubsystemA
    Facade --> SubsystemB
    Facade --> SubsystemC

外观模式的实现方式

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
using System;

// 子系统A
public class SubsystemA
{
public void OperationA()
{
Console.WriteLine("Subsystem A Operation");
}
}

// 子系统B
public class SubsystemB
{
public void OperationB()
{
Console.WriteLine("Subsystem B Operation");
}
}

// 子系统C
public class SubsystemC
{
public void OperationC()
{
Console.WriteLine("Subsystem C Operation");
}
}

// 外观类
public class Facade
{
private SubsystemA subsystemA;
private SubsystemB subsystemB;
private SubsystemC subsystemC;

public Facade()
{
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
subsystemC = new SubsystemC();
}

public void Operation()
{
subsystemA.OperationA();
subsystemB.OperationB();
subsystemC.OperationC();
}
}

外观模式的应用场景

外观模式适用于以下情况:

  1. 需要为一个复杂的子系统提供一个简单的接口。
  2. 客户端与多个子系统之间存在复杂的依赖关系,而希望将这些依赖关系封装在一个统一的接口中。
  3. 希望将子系统和客户端之间的耦合度降到最低,使得系统更易于维护和扩展。

外观模式的优势

  1. 简化接口: 外观模式提供了一个简化的接口,使得客户端更容易使用系统。
  2. 解耦子系统: 外观模式将客户端与子系统解耦,减少了客户端与子系统之间的依赖关系。
  3. 提高灵活性: 外观模式使得系统更容易维护和扩展,通过修改外观类,而不是修改多个子系统的代码。

使用示例

1
2
3
4
5
6
7
8
9
10
11
class Program
{
static void Main()
{
// 创建外观对象
Facade facade = new Facade();

// 调用外观对象的操作方法,实际上会调用多个子系统的操作方法
facade.Operation();
}
}

总结

外观模式是一种结构型设计模式,通过提供一个简化的接口,将系统中的一组接口进行封装,使得客户端更容易使用系统。外观模式常用于需要为复杂的子系统提供一个简单接口、或者降低客户端与子系统之间耦合度的情景。在实际应用中,外观模式能够有效地提高系统的可维护性、可扩展性和灵活性。

适配器模式 - 结构型模式的接口转换魔法

在软件设计中,适配器模式是一种结构型设计模式,它允许将一个类的接口转换为客户端期望的另一个接口。本文将深入讨论适配器模式的概念、实现方式以及在实际应用中的使用场景。

适配器模式的概念

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换为客户端期望的另一个接口。适配器使得原本因接口不匹配而无法一起工作的类可以一起工作。

适配器模式的 UML 类图

classDiagram
    class Target {
        + Request(): void
    }

    class Adaptee {
        + SpecificRequest(): void
    }

    class Adapter {
        - adaptee: Adaptee
        + Request(): void
    }

    Target <|.. Adapter
    Adaptee <|.. Adapter

适配器模式的实现方式

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
using System;

// 目标接口
public interface Target
{
void Request();
}

// 源接口
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee's specific request");
}
}

// 适配器
public class Adapter : Target
{
private readonly Adaptee adaptee;

public Adapter(Adaptee adaptee)
{
this.adaptee = adaptee;
}

public void Request()
{
adaptee.SpecificRequest();
}
}

适配器模式的应用场景

适配器模式适用于以下情况:

  1. 需要使用一个已经存在的类,但其接口不符合系统的需求。
  2. 需要创建一个可以复用的类,与其他不相关的类或不可预见的接口协同工作。
  3. 需要使用一些已经存在的子类,但不可能对每个子类进行适配。

适配器模式的优势

  1. 解耦性强: 适配器模式将目标类和适配者类解耦,使得它们可以独立变化,增强了系统的灵活性。

  2. 复用性好: 已经存在的类可以在适配器中被复用,无需修改原有代码。

  3. 扩展性强: 在不修改适配者和目标类的前提下,可以增加新的适配器类,扩展系统的功能。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Program
{
static void Main()
{
// 创建适配者对象
Adaptee adaptee = new Adaptee();

// 创建适配器对象,并将适配者对象传入
Target adapter = new Adapter(adaptee);

// 客户端通过目标接口调用适配器的方法
adapter.Request();
}
}

总结

适配器模式的意图就是通过接口转换,使本来不兼容的接口可以协作。一次适配也许不能满足我们的需要,项目中我们往往需要做适配器间的互联,随着XML数据的广泛使用,我们还需要专门的适配器设计思路。

适配器模式是一种结构型设计模式,通过将一个类的接口转换为另一个接口,使得原本不兼容的类可以一起工作。适配器模式在实际应用中常用于整合已有的系统,提供统一的接口。在设计中,适配器模式需要权衡代码的灵活性和复杂性,确保达到适配的同时不引入过多的代码复杂性。

桥模式 - 结构型模式的跨越桥梁

在软件设计中,桥模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。本文将深入讨论桥模式的概念、实现方式以及在实际应用中的使用场景。

桥模式的概念

桥模式(Bridge Pattern)是一种结构型设计模式,其核心思想是将抽象部分与实现部分分离,使它们可以独立变化。桥模式通过一个抽象类(或接口)持有一个实现类的引用,从而实现了抽象部分和实现部分的解耦。

桥模式的 UML 类图

classDiagram
    class Abstraction {
        - implementor: Implementor
        + Operation(): void
    }

    class RefinedAbstraction {
        + Operation(): void
    }

    interface Implementor {
        + OperationImpl(): void
    }

    class ConcreteImplementorA {
        + OperationImpl(): void
    }

    class ConcreteImplementorB {
        + OperationImpl(): void
    }

    Abstraction *- Implementor
    RefinedAbstraction --> Abstraction
    RefinedAbstraction --> Implementor
    ConcreteImplementorA --> Implementor
    ConcreteImplementorB --> Implementor

桥模式的实现方式

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
using System;

// 实现部分的接口
public interface Implementor
{
void OperationImpl();
}

// 具体实现类A
public class ConcreteImplementorA : Implementor
{
public void OperationImpl()
{
Console.WriteLine("Concrete Implementor A");
}
}

// 具体实现类B
public class ConcreteImplementorB : Implementor
{
public void OperationImpl()
{
Console.WriteLine("Concrete Implementor B");
}
}

// 抽象部分的类
public abstract class Abstraction
{
protected Implementor implementor;

public void SetImplementor(Implementor implementor)
{
this.implementor = implementor;
}

public abstract void Operation();
}

// 具体抽象类
public class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.OperationImpl();
}
}

桥模式的应用场景

桥模式适用于以下情况:

  1. 当一个类存在两个独立变化的维度,且两个维度都需要独立进行扩展时。
  2. 当一个类需要对多个实现进行选择,并且这些实现可以动态切换时。
  3. 当一个类需要跨越多个层次结构,与多个类合作时。

桥模式的优势

  1. 分离抽象与实现: 桥模式通过将抽象部分与实现部分分离,使得它们可以独立变化,降低了系统的耦合度。

  2. 可扩展性强: 桥模式允许抽象部分和实现部分独立扩展,不影响彼此,提高了系统的可扩展性。

  3. 动态切换实现: 桥模式允许在运行时动态切换实现,灵活性较高。

使用示例

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
class Program
{
static void Main()
{
// 创建具体实现类A
Implementor implementorA = new ConcreteImplementorA();

// 创建具体抽象类,并设置实现类A
Abstraction abstractionA = new RefinedAbstraction();
abstractionA.SetImplementor(implementorA);

// 调用抽象类的操作方法,实际上会调用实现类A的操作
abstractionA.Operation();

// 创建具体实现类B
Implementor implementorB = new ConcreteImplementorB();

// 创建具体抽象类,并设置实现类B
Abstraction abstractionB = new RefinedAbstraction();
abstractionB.SetImplementor(implementorB);

// 调用抽象类的操作方法,实际上会调用实现类B的操作
abstractionB.Operation();
}
}

总结

桥模式是一种重要的结构型设计模式,通过将抽象部分与实现部分分离,使得它们可以独立变化。桥模式的设计思想在多维度的变化和协同工作场景中得到了广泛应用,例如图形系统、操作系统窗口管理等。在实际应用中,桥模式需要根据具体场景权衡抽象和实现的分离程度,确保系统具备足够的灵活性。

代理模式 - 结构型模式的操控者

在软件设计中,代理模式是一种结构型设计模式,它提供了一个代理对象来控制对其他对象的访问。代理模式可以用于多种场景,例如远程代理、虚拟代理、保护代理等。本文将深入讨论代理模式的概念、实现方式以及在实际应用中的使用场景。

代理模式的概念

代理模式(Proxy Pattern)是一种结构型设计模式,其核心思想是通过一个代理对象控制对其他对象的访问。代理对象充当了被代理对象的替代者,可以在访问时添加一些额外的逻辑,例如权限验证、懒加载等。

代理模式的 UML 类图

classDiagram
    class Subject {
        + Request(): void
    }

    class RealSubject {
        + Request(): void
    }

    class Proxy {
        - realSubject: RealSubject
        + Request(): void
    }

    Subject <|.. RealSubject
    Subject <|.. Proxy

代理模式的实现方式

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
using System;

// 抽象主题类
public abstract class Subject
{
public abstract void Request();
}

// 真实主题类
public class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("Real Subject Request");
}
}

// 代理类
public class Proxy : Subject
{
private RealSubject realSubject;

public override void Request()
{
// 在访问真实主题前可以添加一些额外的逻辑
if (realSubject == null)
{
realSubject = new RealSubject();
}

realSubject.Request();

// 在访问真实主题后可以添加一些额外的逻辑
}
}

代理模式的应用场景

代理模式适用于以下情况:

  1. 远程代理: 代理对象可以控制对远程对象的访问,例如通过网络访问远程服务器的对象。
  2. 虚拟代理: 代理对象可以在访问时延迟加载真实对象,提高系统性能。
  3. 保护代理: 代理对象可以控制对真实对象的访问权限,增加了安全性。
  4. 缓存代理: 代理对象可以缓存对真实对象的操作结果,提高系统的响应速度。

代理模式的优势

  1. 控制访问: 代理模式可以控制对真实对象的访问,可以在访问时添加一些额外的逻辑。
  2. 提高性能: 虚拟代理可以延迟加载真实对象,提高了系统的性能。
  3. 增加安全性: 保护代理可以控制对真实对象的访问权限,增加了系统的安全性。
  4. 实现懒加载: 代理模式可以实现懒加载,只有在真正需要时才加载真实对象。

使用示例

1
2
3
4
5
6
7
8
9
10
11
class Program
{
static void Main()
{
// 创建代理对象
Proxy proxy = new Proxy();

// 调用代理对象的操作方法,实际上会调用真实主题对象的操作方法
proxy.Request();
}
}

总结

代理模式是一种结构型设计模式,通过代理对象控制对其他对象的访问。代理模式在多种场景中有广泛的应用,例如远程代理、虚拟代理、保护代理等。在实际应用中,代理模式需要根据具体场景权衡性能、安全性和代码的清晰度。

原型模式 - 创建型模式的对象复制大师

在软件设计中,原型模式是一种创建型设计模式,它通过复制现有对象来创建新对象,从而避免了创建对象时的耗时操作。本文将深入探讨原型模式的概念、实现方式以及在实际应用中的使用场景。

原型模式的概念

原型模式(Prototype Pattern)是一种创建型设计模式,其核心思想是通过复制(克隆)现有对象来创建新对象。这种方式避免了从头创建对象的过程,提高了对象创建的效率。

原型模式的 UML 类图

classDiagram
    class Prototype {
        + Clone(): Prototype
    }

    class ConcretePrototype : Prototype {
        + Clone(): Prototype
        - state: string
    }

原型模式的实现方式

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
using System;

// 原型接口
public interface Prototype
{
Prototype Clone();
}

// 具体原型类
public class ConcretePrototype : Prototype
{
private string state;

public ConcretePrototype(string state)
{
this.state = state;
}

public Prototype Clone()
{
return new ConcretePrototype(this.state);
}

public void ShowState()
{
Console.WriteLine($"State: {state}");
}
}

原型模式的应用场景

原型模式适用于以下情况:

  1. 对象的创建成本较大,但需要频繁地创建相似对象。
  2. 系统要求一个对象在多个场景中使用,但每个场景的状态略有差异。
  3. 需要保护对象的客户端免受对象变化的影响,同时希望能够动态地配置对象。

原型模式的优势

  1. 节省资源: 避免了重复创建相似对象的开销,提高了系统性能和资源利用率。

  2. 动态配置对象: 客户端可以动态地配置克隆对象的状态,实现动态变化。

  3. 简化对象创建: 将对象创建的过程封装在原型中,使得客户端无需关心对象的具体创建细节。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
{
static void Main()
{
// 创建原型对象
ConcretePrototype prototype = new ConcretePrototype("Initial State");
prototype.ShowState();

// 克隆原型对象
ConcretePrototype clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();

// 修改克隆对象的状态
clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();
clonedPrototype = (ConcretePrototype)prototype.Clone();
clonedPrototype.ShowState();
}
}

总结

用原型实例指定创建对象的种类,并且通过拷贝(克隆)这些原型创建新的对象。克隆过程可“繁”可“简”,而且我们往往希望对于克隆过程实施更深入的控制,为了简化开发,我们还要准备点工具类完成不同的克隆过程。

原型模式是一种简单而有效的创建型设计模式,通过复制现有对象来创建新对象,提高了对象创建的效率。在某些场景下,特别是当对象创建成本较大且对象之间的差异较小时,原型模式能够带来显著的性能提升。在实际应用中,使用原型模式需要注意克隆对象的深拷贝和浅拷贝问题。

工厂模式与工厂方法模式 - 创建型模式的巧妙设计

在软件设计中,工厂模式和工厂方法模式是两种创建型设计模式,它们都旨在解决对象的创建问题。本文将深入讨论工厂模式和工厂方法模式的概念、应用场景以及实际代码示例。

工厂模式

工厂模式是一种创建型设计模式,它提供了一个通用的接口来创建对象,但具体的实例化过程由子类决定。这样的设计允许一个类在运行时确定实例化哪个具体类,而不是在编译时进行硬编码。

代码示例

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
public class 简单工厂模式
{
[Fact]
public void Test()
{
Operation oper;
oper = OperationFactory.CreateOperation("+");
oper.numberA = 1;
oper.numberB = 2;
double result = oper.GetResult();
}

public class OperationFactory
{
public static Operation CreateOperation(string operat)
{
Operation oper = null;
switch (operat)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
}
return oper;
}
}

public class Operation
{
public double numberA { get; set; }
public double numberB { get; set; }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
private class OperationAdd : Operation
{
public override double GetResult()
{
double result = numberA + numberB;
return result;
}
}
private class OperationSub : Operation
{
public override double GetResult()
{
double result = numberA - numberB;
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
37
38
39
40
41
42
43
44
/// <summary>
/// 定义一个用于创建对象的接口,让子类决定实例化哪一个子类。工厂方法使一个类的实例化延迟到其子类
/// </summary>
public class 工厂方法模式
{
[Fact]
public void Test()
{
IFactory factory = new AddFactory();
Operation oper = factory.CreateOperation();
oper.numberA = 1;
oper.numberB = 2;
double result = oper.GetResult();
}
class Operation
{
public double numberA { get; set; }
public double numberB { get; set; }
public virtual double GetResult()
{
double result = 0;
return result;
}
}
class OperationAdd : Operation
{
public override double GetResult()
{
double result = numberA + numberB;
return result;
}
}
interface IFactory
{
Operation CreateOperation();
}
class AddFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationAdd();
}
}
}

工厂模式和工厂方法模式的应用场景

  • 工厂模式适用场景: 当一个类负责创建的对象的类不确定,而需要根据具体情况进行选择时,可以使用工厂模式。例如,需要根据配置文件动态选择数据库连接。

  • 工厂方法模式适用场景: 当一个类不知道

它所需要的对象的类,但知道需要某个类来创建对象时,可以使用工厂方法模式。例如,需要在运行时决定创建哪个日志记录器。

工厂方法的意图非常明确,它把类的实例化过程延迟到子类,将new()的工作交给工厂完成。同时,增加一个抽象的工厂定义,解决一系列具有统一通用工厂方法的实体工厂问题。在.NET 平台中,我们可以借助配置、泛型和委托的方法在实现经典模式目的的同时,获得工厂类型与客户程序间更加松散的构造过程。

总结

工厂模式和工厂方法模式都是创建型设计模式,它们通过将对象的创建过程封装在工厂中,提高了代码的灵活性和可维护性。选择使用哪种模式取决于具体的需求和设计情景。这两种模式在实际开发中被广泛应用,能够有效地组织和管理对象的创建过程。

深入理解单例模式 - 创建型模式的精髓

单例模式是一种创建型设计模式,其目的是确保一个类只有一个实例,并提供全局访问点。在许多场景中,单例模式被用于管理全局状态、资源共享以及限制对象的创建。在本文中,我们将深入探讨单例模式的概念、实现方式以及在实际应用中的使用场景。

单例模式的概念

单例模式是设计模式中最简单但也是最常用的模式之一。其核心思想是通过限制一个类只能有一个实例,确保该实例能够被全局访问。这通常通过以下几个要素来实现:

  1. 私有构造函数: 防止外部通过构造函数创建实例。
  2. 私有静态变量: 用于保存实例。
  3. 公有静态方法(全局访问点): 用于获取实例。

单例模式的实现方式

在C#中,实现单例模式的方式有多种,以下是其中两种常见的实现方式:

1. 懒汉式单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// <summary>
/// 懒汉式单例类
/// </summary>
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
public static Singleton GetInstance()
{
//双重锁定
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}

这种实现方式在需要时才创建实例,称为懒汉式。通过 lock 语句确保多线程环境下的安全创建。

2. 饿汉式单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// 懒汉式单例类
/// </summary>
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
public static Singleton GetInstance()
{
//双重锁定
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}

这种实现方式在类加载时就创建实例,称为饿汉式。由于在类加载时就创建,因此不存在多线程安全问题。

单例模式的应用场景

单例模式适用于以下场景:

  1. 资源共享: 当应用中需要共享资源(如配置信息、日志对象)时,单例模式能够确保只有一个实例处理这些共享资源。

  2. 全局状态管理: 当某个对象需要在系统中保存全局状态时,单例模式能够提供一个统一的入口点来管理这个状态。

  3. 唯一访问点: 当某个类的实例只能有一个访问点时,如工厂类、线程池等,单例模式能够确保只有一个实例提供访问点。

单例模式的注意事项

  1. 多线程安全: 在多线程环境下,懒汉式单例模式需要考虑线程安全问题,可通过 lockdouble-check 等方式解决。

  2. 延迟加载: 懒汉式单例模式支持延迟加载,但在需要时创建实例,可能会引入性能开销。

  3. 反序列化安全: 如果单例类可能被序列化和反序列化,需要实现 ISerializable 接口并提供 OnDeserialized 方法,以确保反序列化后仍然是单例。

总结

使用Singleton 模式的意图就是要保证一个类只有一个实例,同时提供客户程序一个访问它的全局访问点。虽然经典Singleton 模式旨在控制实例的数量,但受到种种“隐性”破坏因素的威胁,我们还需要实施各种针对性的实例数量控制手段。

单例模式是一种简单而强大的设计模式,适用于多种场景。通过合理选择懒汉式或饿汉式的实现方式,可以满足不同的需求。在实际应用中,合理使用单例模式能够提高代码的可维护性和整体设计的灵活性。