前言:关于设计模式的内容均是学习心得,请适当参考,不对之处请指正。
应该有很多人跟我一样,coding到一定阶段,总想学下设计模式,提升下能力的级别,但学习过程中,那些书本上的,blog上的都能看得懂,但却很难在实际开发用应用起来。而我现在的感悟是:应该一个个模式慢慢地学,先将面对对象的封装继承多态加深理解,在看完一个设计模式的时候,coding出来,并在coding过程中思考。coding完后,不要急燥,想想以后将怎么用上。
简单工厂模式和单例模式是最易被理解的。
先回忆下,什么时候用虚方法、抽象类、接口?
虚方法:类在业务中是实际已知存在,有真实意思的(其子类当然也有意义),例如有普通固定电话、IP固定电话、传真电话,实际业务中,假定普通固定电话是有意义的,同时可以作为IP电话、传真电话的父类,那么固定电话的MakeCall方法,就可以设计成虚方法。
抽象类:当事务只是一个抽象概念,具体的事情根本不知怎么做的时候用的。例如一个系统中有两种订单(后面可能更多),手机订单和服务订单,那么订单就是一个抽象概念,叫下个订单,实际中根本不知往哪去下。所以应该定义为抽象类,不能实例化,其子类(就那两种订单)也必需去override其抽象方法。以下例子就是用抽象类去实现简单工厂模式滴。
接口:更为抽象,当遇到几类相似的事物,却又抽象不出一个父类,他们之前却有一些共同的地方时就用接口吧。例如一套普通的公司内部使用的系统,大多数表都会有简单的CRUD(增删改查),这就是抽象不出它们有父类,却有共同的特性,这时候,定义一个接口ICRUDAble,让需要增删改查的数据模式都继承自它最合适了,当然这个例子说法上,很难体现它的好处,反而让接口成了个死规矩。
ok,复习完成,简单工厂模式上代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _1_简单工厂模式
{
class Program
{
static void Main(string[] args)
{
#region 不是那么优雅的写法,这就体现不出设计模式的思想出来
//Order order = null;
//Console.WriteLine("你要下什么订单?mobile:手机订单;service服务订单");
//string input = Console.ReadLine();
//switch (input)
//{
// case "mobile":
// order = new MobilePhoneOrder();
// break;
// case "service":
// order = new ServiceOrder();
// break;
// default:
// Console.WriteLine("非法订单");
// return;
//}
//order.Add();
//Console.ReadKey();
#endregion
#region 利用上简单工厂模式的写法
Console.WriteLine("你要下什么订单?mobile:手机订单;service服务订单");
string input = Console.ReadLine();
Order order = OrderFactory.CreateOrderSimplyFactory(input);
if (null==order)
{
//突然想说,以前搞不懂设计模式的一大原因,就是书上的用例多少有点牵强,也很难在实际工厂中联想应用到哪里可以用上。
//就连这个null==order那些大神们都不写,看多了自然会对这个世界产生怀疑,虽然我知道用意是想突出设计模式。
return;
}
order.Add();
Console.ReadKey();
#endregion
}
/// <summary>
/// 订单是一样很抽象的东西,因为不知是什么类型的订单,所以不能有个具体的Add方法
/// 否则就可以用普通类,Add方法用virtual就够
/// 因为见到《大话设计模式》中,介绍简单工厂的时候,用基类是普通因。将实现多态的方法用虚方法去实现了
/// </summary>
public abstract class Order
{
public abstract void Add();
//这里应该有订单的属性
}
public class MobilePhoneOrder : Order
{
public override void Add()
{
Console.WriteLine("手机订单已经下达成功,我做了伟大的持久化保存");
}
}
public class ServiceOrder : Order
{
public override void Add()
{
Console.WriteLine("服务订单已经下达成功,这时候应该通知人员进行服务");
}
}
public class OrderFactory
{
public static Order CreateOrderSimplyFactory(string name)
{
Order order = null;
switch (name)
{
case "mobile":
order = new MobilePhoneOrder();
break;
case "service":
order = new ServiceOrder();
break;
default:
break;
}
return order;
}
}
}
}
讲解:
order类为MobileOrder、ServiceOrder的父类,都有统一的Add方法,
而业务中,需要根据订单类型,针对两种不同订单对不用的添加操作。
那就是用父类order接收对象的创建,其Add方法的调用就不需要改动了,没错,就是为了让Add方法不用修改,动了这么大工夫。
这时候,马上也会怀疑人生:如果再多一种订单业务出来,switch那里还是得改,是的,我也很它很不顺眼,但至少,逻辑调用的时候,不再需要做改变了。比什么设计模式什么思想都没有的if switch去实现要进步了好多。
最后补充:订单本身是抽象的,在实际业务中没有意义,所以它应该是抽象的,说到大话设计模式一书中,讲解大话设计模式用的是虚方法,个人认为,这同样可以,得看实际业务中父类有没有意义,并且在switch中,应该也能把父类也给生产出来。