前言:
"软件模式的伟大之处, 就在于他们传达了许多有用的设计思想. 所以, 在学习了大量模式之后, 就理应成为非常优秀的软件设计人员, 不是吗? 当学习、使用了几十个设计模式之后, 我也曾这样认为. 模式帮助我开发灵活的框架, 帮助我构建坚固、可扩展的软件系统. 但是几年之后, 我却发现自己在模式方面的知识和使用模式的方式总是使我在工作中犯过度设计的错误.
设计技术进一步提高之后, 我发现自己使用模式的方式逐渐发生了变化: 我开始 '通过重构实现模式、趋向模式和去除模式(refactoring to, towards, and away from pattern)', 而不再是预先(up-front)设计中使用模式, 也不再过早地在代码中加入模式. 这种使用模式的新方式来自于我对极限变成(xp)设计实践的采用, 它帮助我即避免了过度设计, 又不至于设计不足. " -- 引自 Refactoring to Patterns, 当然是翻译版
在我决定使用新方法学习设计模式之前, 我也看过不少设计模式的资料和书籍, 但大部分都是当时懂了, 不久之后, 再度遗忘, 仿佛没学过一般(主要是在平时不用, 所以不忘我都不信了). 干脆记录下来, 以后就算不用, 只要有网络的地方, 还可以拿出来看看.
学习的顺序, 就不按照类型去区分学习了, 看心情来选择学习.
一、简单工厂
首先, 我们有三件产品, 普通轿车,越野,跑车, 创建完之后, 会返回这三种产品中的一件, 但是我又不知道是哪一件, 怎么办呢, 同一个方法返回不同的几种东西.
面向对象有一种很强大的特性, 多态. 首先要抽象他们, 提取出他们共同的部分, 比如, 相同的行为(启动, 刹车, 加速, 行驶), 或者相同的特征(都属于车, 都有轮子). 对于他们不同的部分, 可以放在各自的类中. 此处就是提取抽象, 隔离变化的思想.
那按照这种思想, 先分析他们相同的部分, 然后提取出来, 形成一个基类.
public enum EnumCar { SUV, Normal, Sports } /// <summary> /// 抽象基类, 也可以做成接口, 或者就是一个普通类, 主要是为了实现多态 /// </summary> public abstract class Car { /// <summary> /// 车名 /// </summary> public string Name { get; set; } /// <summary> /// 车型 /// </summary> public string CarType { get; set; } /// <summary> /// 汽车品牌 /// </summary> public string Brand { get; set; } /// <summary> /// 启动汽车 /// </summary> public virtual void Start() { Console.WriteLine(this.Name + " Start "); } }
接下来, 可以建各自的类了.
public class Normal : Car { public Normal() { this.CarType = "普通轿车"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } } public class Sports : Car { public Sports() { this.CarType = "跑车"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } } public class SUV : Car { public SUV() { this.CarType = "越野"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } }
做好这些之后, 就可以开始 简单工厂的部分了. 那建工厂之前, 还是要明确一下, 这个工厂的职责, 通过传入不同的类型, 来创建不同的产品. 相同的入参, 不同的返回值.
public class CarFactory { public static Car Create(EnumCar car) { switch (car) { case EnumCar.SUV: return new SUV(); case EnumCar.Normal: return new Normal(); case EnumCar.Sports: return new Sports(); default: return new Normal(); } } }
ok, 一切弄完之后, 就可以测试一下了:
static void Main(string[] args) { Car car = CarFactory.Create(EnumCar.SUV); car.Start(); Console.ReadKey(); }
结果如下:
二、类图
三、自己的理解
所有的设计, 都是为了简化应用. 无病呻吟, 实非目的, 所以就根据我在项目中的所见所闻所用, 列举一下几个使用场景.
1. 服务端可以通过获取客户端传入的参数或者根据配置文件中配置的项, 来创建对应的类, 以此来执行不同的一套操作, 完成相同的工作, 当然, 结果可以是不一样的.
对我映像比较深的一个项目实例, 就是配合项目配置文件(appsetting), 在策略模式中, 选择创建哪一种缓存机制, 来达到选择使用缓存的功能.
2. 可以改进抽象工厂. 具体在抽象工厂中介绍.
四、问题
从这个例子中, 能看到, 我能新建的产品, 是一定的, 或者说是死的, 如果我想新加一种产品, 在不改代码的情况下, 是加不进去的. 怎么加进去呢? 下一篇揭晓谜底.