设计模式

设计模式是为了解决日常软件开发问题而设计的常见构建模块。一些基本术语和这些模式的示例可以在我们日常生活中看到。设计模式大体上可以分为三种类型:

  1. 创建型模式:这些模式设计用于类的实例化。它们可以是类创建模式或对象创建模式。

  2. 结构型模式:这些模式是针对类的结构和组成来设计的。大多数这种模式的主要目标是增加涉及的类的功能,而不改变其结构。

  3. 行为型模式:这些模式是根据一个类与其他类的交互方式来设计的。

工厂模式 (Factory Pattern)

工厂模式是一种方法调用,它使用抽象类及其实现,帮助开发者选择最合适的类来完成某个任务。

首先,让我们创建几个类来演示如何使用这个模式。这里我们以银行系统为例。

public abstract class Transaction
{
     private string _sourceAccount;

     // 在大多数情况下可能不需要,但转账、关闭和更正时可能需要。
     private string _destinationAccount;
   
     private decimal _amount;
     public decimal Amount { get { return _amount; } }
   
     private DateTime _transactionDate;
     private DateTime _effectiveDate;

     public Transaction(string source, string destination, decimal amount)
     {
          _sourceAccount = source;
          _destinationAccount = destination;
          _amount = amount;
          _transactionDate = DateTime.Now;
     }

     public Transaction(string source, string destination, decimal amount, DateTime effectiveDate) 
        : this(source, destination, amount)
     {
          _effectiveDate = effectiveDate;
     }

     protected decimal AdjustBalance(string accountNumber, decimal amount)
     {
          decimal newBalance = decimal.MinValue;

          using(Mainframe.ICOMInterface mf = new Mainframe.COMInterfaceClass())
          {
               string dateFormat = DateTime.Now.ToString("yyyyMMdd HH:mm:ss");
               mf.Credit(dateFormat, accountNumber, amount);
               newBalance = mf.GetBalance(DateTime.Now.AddSeconds(1), accountNumber);
          }
          
          return newBalance;
     }
     
     public abstract bool Complete();
}

这个 Transaction 类是不完整的,因为有很多类型的交易,例如:

  • 开户
  • 存款
  • 取款
  • 转账
  • 罚款
  • 更正
  • 关闭

为了简单起见,我们将创建两个交易类型类:存款(Credit)和取款(Withdrawal)。

public class Credit : Transaction
{
     // 这里隐藏实现细节

     public override bool Complete()
     {
          this.AdjustBalance(_sourceAccount, amount);
     }
}

public class Withdrawal : Transaction
{
     // 这里隐藏实现细节

     public override bool Complete()
     {
          this.AdjustBalance(_sourceAccount, -amount);
     }
}

问题是,这些类做的事情大同小异,所以如果我们能提供一些值,并且让程序自动选择合适的类类型,就会更方便。我们可以通过一些方式区分不同类型的交易:

  • 正数值表示存款。
  • 负数值表示取款。
  • 有两个账户号码且为正数值表示转账。
  • 有两个账户号码且为负数值表示关闭账户。
  • 等等。

接下来,我们创建一个新的类,使用一个静态方法来处理这些逻辑,并命名为 Factory

public class TransactionFactory
{
     public static Transaction Create(string source, string destination, decimal amount)
     {
          if(!string.IsNullOrEmpty(destination))
          {
               if(amount >= 0)
                    return new Credit(source, null, amount);
               else
                    return new Withdrawal(source, null, amount);
          }
          else
          {
               // 其他实现可以在这里处理
          }
     }
}

现在,你可以使用这个类来完成所有逻辑和处理,并确保返回的类型是正确的。

public class MyProgram
{
     static void Main()
     {
          decimal randomAmount = new Random().Next() * 1000000;
          Transaction t = TransactionFactory.Create("123456", "", randomAmount);
          // t.Complete(); <-- 这将执行请求的交易。
 
          Console.WriteLine("{0}: {1:C}", t.GetType().Name, t.Amount);
     }
}

单例模式 (Singleton)

单例模式仅实例化一个对象,并在整个过程的生命周期内重用这个对象。如果你希望该对象保持状态,或创建对象的过程需要大量资源时,这种模式会非常有用。下面是一个基本的实现:

public class MySingletonExample
{
   private static object obj = new object();
   private volatile static Hashtable _sharedHt;

   public static Hashtable Singleton
   {
     get 
     {
         if(_sharedHt == null){
             lock(obj){
                  if(_sharedHt == null){
                     _sharedHt = new Hashtable();
                  }
             }
         }
         return _sharedHt;
     }
   }

   // 类的实现代码...
}

Singleton 属性会向所有调用者暴露相同的实例。在第一次调用时,初始化该对象,在随后的调用中使用相同的对象。

单例模式的应用示例包括:

  • ConfigurationSettings(通用设置读取器)
  • HttpApplication(ASP.NET 中的应用程序对象)
  • HttpCacheUtility(ASP.NET 中的缓存对象)
  • HttpServerUtility(ASP.NET 中的服务器对象)
最后修改: 2025年01月12日 星期日 00:20