一, 前言
前几天阅读一框架文档, 里面有一段这样的描述 "从对象工厂中........." , 促使写下本文. 尽管一些模式简单和简单, 但是常用, 有用.
结合最近一个项目场景回顾一下里面应用到的一些模式 < Singleton,Factory,Strategy>.
Singleton: 创建型模式, 负责创建维护一个全局唯一实例
Factory: 创建型模式, 对象工厂负责根据标识创建或获取具体的实例对象
Strategy: 行为型 / 运行时模式, 策略负责根据标识控制应用运行时的行为
示例代码: https://github.com/Shawn-china/DesignPatternDemo.git
二, 场景上下文
项目需求 / 场景: 通过增加辅助工具使用脚本程序对特定应用程序进行 "自动化测试", 内容包括: 点击按钮, 选择菜单, 读取控件内容等.
原始实现: 脚本程序 < AutoIt > 通过计算坐标的方式对特定应用程序进行 "自动化测试". 缺点: 脚本程序工作量大, 依赖按钮屏幕坐标, 坐标计算繁杂, 依赖屏幕分辨率等.
目标程序简化图:
图 1 目标程序
使用辅助工具前 :
图 2 未使用辅助工具
使用辅助工具后:
图 3 使用辅助工具
三, 分析, 设计
这里只对 辅助工具进行分析设计, 其它略过.
1, 图 1 目标程序有以下主要特点:
• 目标程序分为 A-E 五个功能区
• 每个功能区有按钮, 菜单等相似功能
• 每个功能区有特有功能
2, 辅助工具对外提供统一调用
3, 辅助工具可以被重复调用, 但不支持并发操作
基于以上分析:
1, 将 Operator < 操控代码或具体操控行为 > 分为五个具体的 Operator 分别为: AOperator ,BOperator ,COperator ,DOperator ,EOperator , 分别对应操作不同的应用程序区域.
2, 使用创建型模式管理 Operator
3, 使用锁机制, 限制并发
4, 外层封装一个单例
四, UML
图 4 UML 类图
五, Code Show
1,AuxiliaryToolSingleton 对外提供调用, 并用锁机制控制并发.
- using System;
- using System.Threading;
- using DesignPatternDemo.Operator;
- namespace DesignPatternDemo
- {
- public class AuxiliaryToolSingleton
- {
- public static Semaphore OperatorSemaphore = new Semaphore(1, 1);
- private static readonly object OperatorLock = new object();
- public static AuxiliaryToolSingleton Instance = new AuxiliaryToolSingleton();
- private AuxiliaryToolSingleton()
- {
- RegistorOperator(OperatorFactory.Instance);
- }
- public void CallOperator(string operatorName, params string[] operatorParams)
- {
- //OperatorSemaphore.WaitOne();
- lock (OperatorLock)
- {
- Console.WriteLine($"Call method CallOperator :{operatorName} .Current Thread:{Thread.CurrentThread.ManagedThreadId}");
- BaseOperator concreteOperator = OperatorFactory.Instance.GetOperator(operatorName);
- concreteOperator.InitializationParameters(operatorParams);
- concreteOperator.Execute();
- }
- //OperatorSemaphore.Release();
- }
- public static void RegistorOperator(OperatorFactory factory)
- {
- factory.Register(nameof(AOperator), new AOperator());
- factory.Register(nameof(BOperator), new BOperator());
- factory.Register(nameof(COperator), new COperator());
- factory.Register(nameof(DOperator), new DOperator());
- factory.Register(nameof(EOperator), new EOperator());
- }
- }
- }
- View Code AuxiliaryToolSingleton
2,BaseOperator 操控基类, 包含一些公共方法, 虚方法, 参数信息.
- using System;
- using System.Threading;
- namespace DesignPatternDemo.Operator
- {
- public class BaseOperator
- {
- public string Name { get; set; }
- public string Description { get; set; }
- public void Execute()
- {
- //ToDo
- Thread.Sleep(new Random().Next(0, 5) * 1000);
- Console.WriteLine($"Execute concrete operator:{GetType().Name} .Current Thread:{Thread.CurrentThread.ManagedThreadId}");
- ConcreteOperate($"{GetType().Name}");
- }
- public void InitializationParameters(params string[] operatorParams)
- {
- //ToDo
- Console.WriteLine($"Initialization Parameters :{GetType().Name}");
- }
- private void ConcreteOperate(string mark)
- {
- // ToDo
- Console.WriteLine($"The concrete operation :{mark} was performed successfully .\r\n");
- }
- public virtual void ClickButtonByMark(string mark)
- {
- // ToDo
- ConcreteOperate(mark);
- }
- public virtual void ClickPopupMenuByMark(string mark)
- {
- // ToDo
- ConcreteOperate(mark);
- }
- public virtual void SelectDropdownBoxByIndex(int dropBoxIndex)
- {
- // ToDo
- ConcreteOperate($"{dropBoxIndex}");
- }
- }
- }
- View Code BaseOperator
3,AOperator 具体操控类 < 比如点击按钮 >, 实现 ISpecialOperateA, 继承 BaseOperator .
- using System;
- namespace DesignPatternDemo.Operator
- {
- public class AOperator : BaseOperator, ISpecialOperateA
- {
- public void SetContent(string content)
- {
- //ToDo
- Console.WriteLine($"Filled the content:{content} successfully");
- }
- public string GetContent()
- {
- //ToDo
- return $"{new Random().Next()}{Guid.NewGuid()}";
- }
- }
- }
- namespace DesignPatternDemo.Operator
- {
- public interface ISpecialOperateA
- {
- void SetContent(string content);
- string GetContent();
- }
- }
- View Code AOperator
4,BOperator ,COperator ,DOperator 具体操控类
- namespace DesignPatternDemo.Operator
- {
- public class BOperator : BaseOperator
- {
- }
- }
- namespace DesignPatternDemo.Operator
- {
- public class COperator : BaseOperator
- {
- }
- }
- namespace DesignPatternDemo.Operator
- {
- public class DOperator : BaseOperator
- {
- }
- }
- View Code Concrete Operator
5,EOperator 具体操控类 < 比如操控树形控件 >, 实现 ISpecialOperateE, 继承 BaseOperator .
- using System;
- namespace DesignPatternDemo.Operator
- {
- public class EOperator : BaseOperator, ISpecialOperateE
- {
- public void ClickTreeviewByMark(string mark)
- {
- //ToDo
- Console.WriteLine($"{mark}: execution succeed");
- }
- }
- }
- namespace DesignPatternDemo.Operator
- {
- public interface ISpecialOperateE
- {
- void ClickTreeviewByMark(string mark);
- }
- }
- View Code EOperator
6,Factory 工厂类基类, 可根据 key 注册, 删除, 获取具体类. 创建型模式的一种.
- using System.Collections.Generic;
- namespace DesignPatternDemo
- {
- public class Factory<TF, TV> where TF : new()
- {
- protected Factory()
- {
- KeyValues = new Dictionary<string, TV>();
- }
- public static TF Instance { get; set; } = new TF();
- private Dictionary<string, TV> KeyValues { get; }
- public TV GetItem(string key)
- {
- KeyValues.TryGetValue(key, out TV find);
- return find;
- }
- public void Register(string key, TV t)
- {
- UnRegister(key);
- KeyValues.Add(key, t);
- }
- public void UnRegister(string key)
- {
- if (KeyValues.ContainsKey(key)) KeyValues.Remove(key);
- }
- }
- }
- View Code Factory
7,OperatorFactory 具体工厂, 继承 Factory .
- using DesignPatternDemo.Operator;
- namespace DesignPatternDemo
- {
- public class OperatorFactory : Factory<OperatorFactory, BaseOperator>
- {
- public BaseOperator GetOperator(string operatorName)
- {
- return GetItem(operatorName);
- }
- }
- }
- View Code OperatorFactory
8,Program 控制台程序, 分别使用并行库和 Task 多线程调用模拟.
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- using DesignPatternDemo.Operator;
- namespace DesignPatternDemo
- {
- internal class Program
- {
- private static void Main(string[] args)
- {
- Console.WriteLine("Hello World!");
- List<string> concreteOperators = GetConcreteOperators();
- Parallel.ForEach(concreteOperators, current => { CallOperator(current); });
- foreach (string operatorName in concreteOperators)
- {
- Task concreteTask = new Task(() => { CallOperator(operatorName); });
- concreteTask.Start();
- }
- Console.ReadKey();
- }
- private static List<string> GetConcreteOperators()
- {
- List<string> concreteOperators = new List<string>
- {
- nameof(AOperator),
- nameof(BOperator),
- nameof(COperator),
- nameof(DOperator),
- nameof(EOperator)
- };
- return concreteOperators;
- }
- private static void CallOperator(string operatorName, params string[] operatorParams)
- {
- AuxiliaryToolSingleton auxiliaryTool = AuxiliaryToolSingleton.Instance;
- auxiliaryTool.CallOperator(operatorName, operatorParams);
- }
- }
- }
- View Code Program
六, 说明, 小结
1, 本文只是为了说明回顾一些模式的使用, 原始项目的业务, 代码结构, 实现语言均作了更换或简化.
2,UML 所描述, 可以使用任何 OO 语言实现.
3, 如果条件判断很多可以使用:"表驱动法",Strategy pattern 规避.
4, 模式套路与之相应的场景.
5,Demo 代码环境: vs2017 .Net Core2.2
来源: https://www.cnblogs.com/kkx5211/p/11139973.html