您的位置:首页 > 其它

简单工厂模式和策略模式的区别

2015-02-13 08:48 232 查看
最近一直在抽时间研究设计模式,之前对设计模式也有一定的了解,但是都没有平心静气的去研究过,只是了解了一些皮毛,最近打算再深入研究一下,重新打开了设计模式的数据,对之前的疑问一个个的刨根问底,今天看了简单工厂模式和策略模式看的人有点小晕,两个的大概思路没有怎么变,都是通过多态去减少代码的耦合度,怎么看两个都是如出一辙,最后终于找到了两个的本质区别,在此和大家分享下:

先上代码:

简单工厂模式:

// 抽象类
abstract class AbsClass
{
// 抽象方法:提供一些类的算法操作
public abstract void acceptCash(double money);
}
// 继承自抽象类
class A:AbsClass
{
// 具体方法:提供一些类的算法操作
public override double acceptCash(double money)
{
Console.WriterLine("A类方法");
}
}

// 继承自抽象类
class B:AbsClass
{
// 具体方法:提供一些类的算法操作
public override double acceptCash(double money)
{
Console.WriterLine("B类方法");
}
}

// 现金收取工厂
class CashFactory
{
//根据条件返回相应的对象
public static AbsClass createCashAccept(string type)
{
AbsClass cs = null;
switch (type)
{
case "A":
cs = new Al();
break;
case "B":
cs = new B();
break;
case "...":
........ ....
break;
}
return cs;
}
}


客户端调用:

// 利用简单工厂模式根据下拉选择框,生成相应的对象

AbsClass csuper = CashFactory.createCashAccept("A");
csuper.acceptCash();


策略模式:

前面的类没有任何变化,只是把Factory变成了CashContext策略类

//策略Context
class CashContext
{
//声明一个现金收费父类对象
private AbsClass cs;

//设置策略行为,参数为具体的现金收费子类(正常,打折或返利)
public CashContext(AbsClass csuper)
{
this.cs = csuper;
}

//得到现金促销计算结果(利用了多态机制,不同的策略行为导致不同的结果)
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}


客户端调用:

AbsClass cc = null;
switch (cbxType.SelectedItem.ToString())
{
case "A":
cc = new CashContext(new A());
break;
case "B":
cc = new CashContext(new B());
break;
case "...":
... ....
break;
}
cc.GetResult(...);


简单概括总结一下:

策略模式和简单工厂模式看起来非常相似,都是通过多态来实现不同子类的选取,这种思想应该是从程序的整体来看得出的。如果从使用这两种模式的角度来看的话,我们会发现:

简单工厂模式中,客户端只需要传递相应的条件就能得到想要的一个对象,然后通过这个对象实现算法的操作。

策略模式,客户端必须首先创建一个想使用的类对象,然后将该对象作为参数传递进去,通过该对象调用不同的算法。

在简单工厂模式中实现了通过条件选取一个类去实例化对象,策略模式则将选取相应对象的工作交给模式的使用者,它本身不去做选取工作。

名词理解:

工厂(Factory)模式我们可以做如下理解,假设有一个Audi的公司生产汽车(似乎也不用假设了),它掌握一项核心的技术就是生产汽车,另一方面,它生产的汽车是有不同型号的,并且在不同的生产线上进行组装。当客户通过销售部门进行预定后,Audi公司将在指定的生产线上为客户生产出它所需要的汽车。

策略(Strategy)模式在结构上与工厂模式类似,唯一的区别是工厂模式实例化一个产品的操作是在服务端来做的,换句话说客户端传达给服务端的只是某种标识,服务端根据该标识实例化一个对象。而策略模式的客户端传达给服务端的是一个实例,服务端只是将该实例拿过去在服务端的环境里执行该实例的方法。这就好比一个对汽车不甚了解的人去买车,他在那一比划,说要什么什么样的,销售部门根据他的这个“比划”来形成一份订单,这就是工厂模式下的工作方式。而策略模式下那个顾客就是个行家,他自己给出了订单的详细信息,销售部门只是转了一下手就交给生产部门去做了。

通过两相对比,我们不难发现:

采用工厂模式必须提供足够灵活的销售部门,如果用户有了新的需求,销售部门必须马上意识到这样才可以做出合适的订单。所以倘一款新车出来了,生产部门和销售部门都需要更新,对顾客来说也需要更新对新车的描述,所以需要改动的地方有三处

而策略模式中的销售部门工作比较固定,它只负责接受订单并执行特定的几个操作。当一款新车出来时,只需要对服务端的生产部门和客户端的代码进行更新,而不需要更新销售部门的代码。

技术支持:

简单工厂和策略的基础都是因为面向对象的封装与多态。他们实现的思想都是先设定一个抽象的模型并从该模型派生出符合不同客户需求的各种方法,并加以封装。

模型:

Audi公司的产品有A6, A4, TT, R8...我们如果将每种车的生产做一个方法,那么我们的模型结构应该是这样的
namespace ConsoleApplication5
{
class Audi
{
public void CreateA4()
{
//Do someting
}

public void CreateA6()
{
//Do something
}

public void CreateTT()
{
//Do something
}
}
}


设想一下如果Audi出了一款新车,那么我们必须要在Audi这个类里边添加新的方法,这就要求总公司提供对Audi这个类的修改权限,如果新车项目的负责人对其他车型的负责人有什么意见,它可以轻而易举的改乱他们的代码,让他们的工作陷入瘫痪(当然现实中没有人会这么干)。我们的目标是新生产线的项目负责人只有权限对自己的项目情况作出修改,除此之外他一无所知。

我们可以考虑如下的模型结构:

namespace ConsoleApplication5
{
abstract class BaseFactory
{
public abstract void MakeCar();
}
class A6Factory : BaseFactory
{
public override void MakeCar()
{
Console.WriteLine("Auti A6 is created");
}
}
class A4Factory : BaseFactory
{
public override void MakeCar()
{
Console.WriteLine("Auti A4 is created");
}
}
class TTFactory : BaseFactory
{
public override void MakeCar()
{
Console.WriteLine("Auti TT is created");
}
}
class R8Factory : BaseFactory
{
public override void MakeCar()
{
Console.WriteLine("Auti R8 is created");
}
}
class SelectCarFactoryPattern
{
static BaseFactory bf = null;
public static void OrderCar(string strCarType)
{
switch (strCarType)
{
case "A6":
bf = new A6Factory();
bf.MakeCar();
break;
case "A4":
bf = new A4Factory();
bf.MakeCar();
break;
case "R8":
bf = new R8Factory();
bf.MakeCar();
break;
default:
Console.WriteLine("Error car");
break;
}
}
}
class SelectCarStrategyPattern
{
BaseFactory carFactory = null;
public SelectCarStrategyPattern(BaseFactory carFactory)
{
this.carFactory = carFactory;
}
public void OrderCar()
{
this.carFactory.MakeCar();
}
}
}


这种结构的好处是将每一条生产线进行了封装,在必要的情况下可以使他们的源代码在彼此之间不可见,这一点正是我们所希望看到的。

另外如果每条生产线涉及的代码量很大,这种结构也可以避免重复编译,我们只需要对新增加的生产线进行编译,而之前的生产线我们甚至连动都不需要动。到目前为止,简单工厂模式和策略模式没有什么区别。

工厂模式和策略模式的区别在于实例化一个对象的位置不同,对工厂模式而言,实例化对象是放在服务端的,下面这个类就是用来做这个的。

class SelectCarFactoryPattern
{
static BaseFactory bf = null;
public static void OrderCar(string strCarType)
{
switch (strCarType)
{
case "A6":
bf = new A6Factory();
bf.MakeCar();
break;
case "A4":
bf = new A4Factory();
bf.MakeCar();
break;
case "R8":
bf = new R8Factory();
bf.MakeCar();
break;
default:
Console.WriteLine("Error car");
break;
}
}
}


而策略模式实例化对象的操作在客户端,服务端的“销售部门”只负责传递该对象,并在服务端的环境里执行特定的操作。正如下面这个类所做的:

class SelectCarStrategyPattern
{
BaseFactory carFactory = null;
public SelectCarStrategyPattern(BaseFactory carFactory)
{
this.carFactory = carFactory;
}
public void OrderCar()
{
this.carFactory.MakeCar();
}
}


下面是服务端在两种模式下实例化一个对象并进行操作的示例,工厂模式要求服务端的销售部门足够灵敏,而策略模式由于对策略进行了封装,所以他的销售部门比较傻,需要客户提供足够能区分使用哪种策略的参数,而这最好的就是该策略的实例了


namespace ConsoleApplication5
{
class Customer
{
static void Main(string[] args)
{
//This part is the customer part code for simple factory pattern
Console.WriteLine("Please select your car from 'A6', 'A4', 'R8'");
string strTemp = Console.ReadLine();
SelectCarFactoryPattern.OrderCar(strTemp);

//This part is the customer part code for strategy pattern
SelectCarStrategyPattern scstrategy = new SelectCarStrategyPattern(new A4Factory());
scstrategy.OrderCar();
}
}
}


/article/1356694.html

/article/5214290.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: