先来看一下设计模式常见的书面定义:
设计模式更多的是一种实际应用中经验的基类和总结,并得到了多数人的认可和验证,经过更规范的整理和分类及命名,成为了一种众所周知的知识体系。
0.1 设计模式的分类一般情况下说到的设计模式都是指Gof著作中所讲述的23中经典设计模式。
创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
上学的时候经常跟室友一起玩儿War3,我一直比较钟情于暗夜精灵族,暗夜精灵有4个灰常厉害的英雄,每个英雄都会有4个技能。刚开始学习面向对象思想的时候,我已经知道“英雄”可以定义成一个类,假设每个英雄出场时候都要秀一下自己华丽的四个技能,我们在构造函数中传递英雄名称,构造不同的英雄对象。
英雄类 Hero { _name; 构造函数 Hero(string name) { _name = name; } 秀出自己的技能 ShowSkills() { switch (_name) { : Console.WriteLine(); break; : Console.WriteLine(); break; : Console.WriteLine(); break; : Console.WriteLine(); break; default: break; } } }
英雄轮流秀出的自己的技能(排名不分先后)
class Program { static void Main(string[] args) { Hero dh = ); dh.ShowSkills(); Hero wd = ); wd.ShowSkills(); Hero kog = ); kog.ShowSkills(); Hero pom = ); pom.ShowSkills(); } }
输出结果
上面的代码存在的问题主要有2个:
这里就涉及到了面向接口编程的重要原则。
通常接口用来定义实现类的外观,提取实现类共有的行为定义。接口类似于一种契约,根据外部应用的需要,约定了实现类应该实现的功能,而具体内部如何实现,应由具体的实现类控制,同时具体的实现类除了要实现接口规定的行为外,还可以根据需要实现自己独有的行为,也就是说实现类的功能应包含但不仅限于接口定义的功能。
由于外部调用和内部实现被接口隔离开了,外部调用只通过接口调用,也就是说只要接口不变,内部具体实现的变化就不会对外部调用产生任何影响。这样使用接口的好处就很明显了,当我们增加其他英雄的时候只需要增加一个实现英雄接口的具体实现类既可,对原有已实现的不分不会造成任何影响。提现了接口“封装隔离”的思想。
定义英雄接口:
英雄接口定义 IHero { 秀技能 ShowSkills(); }
不同英雄的具体实现:
恶魔猎手 DH : IHero { 秀出自己的技能 ShowSkills() { Console.WriteLine(); } }
守望者 WD : IHero { 秀出自己的技能 ShowSkills() { Console.WriteLine(); } }
丛林守护者 KOG : IHero { 秀出自己的技能 ShowSkills() { Console.WriteLine(); } }
月亮女祭司 POM : IHero { 秀出自己的技能 ShowSkills() { Console.WriteLine(); } }
修改外部调用部分,同样每个英雄都正确的秀出了自己的技能。
IHero dh = new DH(); dh.ShowSkills(); IHero wd = new WD(); wd.ShowSkills(); IHero kog = new KOG(); kog.ShowSkills(); IHero pom = new POM(); pom.ShowSkills(); Console.ReadLine();
到这里我们就会发现了新的问题,上面说过接口的作用的就是封装隔离,外部调用只知道接口的存在,不应该依赖于具体的实现类。而接口又是没有办法通过new关键字进行实现话的,如何解决这个矛盾?
2 简单工厂模式简单工厂模式并不包含在上述23种经典设计模式之中,也有人说简单工厂并不能算得上一个设计模式。不管怎么说,简单工厂却是实实在在的简单易用,还记得当年还在学校的时候,由于没有经过实际项目的历练,在编码经验不足的情况下,去试着了解设计模式的时候,大部分设计模式是无法深入理解的,也就只有看到简单工厂模式的时候会惊呼:“原来还可以这样”抑或“原来我一直用的就是简单工厂”。
简单来说,简单工厂就是通过定义一个工厂类,这个工厂类提供了一个创建具体实例的功能,外部调用只需要告诉工厂需要什么类型的实例,工厂负责创建这个实例,外部调用无需关心其具体实现,从而达到真正的接口隔离的目的。
简单工厂类中创建具体实例的方法一般定义为静态方法,从而可以避免在外部调用的时候再new简单工厂的对象,因此简单工厂模式一般也被成为静态工厂模式。
我们定义一个简单工厂类。