理解软件设计模式 - 命令模式

前言

最近学习软件设计模式看到命令模式,找了好几篇文章看啊看,都是什么Receiver啦,Invoker啦,Command啦等等之类的各种新名词,晦涩难懂,看得实在头大。。。。
后来转念一想,卧槽!那么多新名词,其实都是我们实实在在用着的东西。

“经典” 的命令模式

为什么叫“经典”的命令模式呢?因为经典的都让人搞不懂
命令模式的描述大多都是这样的:

在软件开发系统中,“方法的请求者”与“方法的实现者”之间经常存在紧密的耦合关系,这不利于软件功能的扩展与维护。例如,想对方法进行“撤销、重做、记录”等处理都很不方便,因此“如何将方法的请求者与实现者解耦?”变得很重要,命令模式就能很好地解决这个问题。
– 引用自 C语言中文网

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
–引用自 RUNOOB

以及uml(引用自 RUNOOB):
引用自RUNOOB

对于我来说看见上面的描述
我的大脑:我拒绝,我不要,我看不懂
我:俺也一样

后来脑子有了自己的想法

想必大家都了解过IOC,如果不了解也没关系,请直接略过。那你一定了解经典的三层架构(你不知道的话我直播吃键盘!如果你真的不了解我连主机都给吃喽,如果你确定、一定以及肯定没了解过,那就当我什么都没说)

IOC是怎么解决耦合的? 就是把耦合交给了Container。
三层是怎么解决耦合的? 就是不解决。

那么命令模式就有了用武之地,我们在三层中Service层的类中要使用Dao层中的类一般是这样的:

//数据访问层
public class UserDao
{
	public User getUser(){
		return User;
	} 
}
//业务逻辑层
public class UserService 
{
	UserDao userDao = new UserDao();
	
	public User getUser(){
		return userDao.getUser();
	}
}

我们在UserService类里直接new了一个UserDao出来,可以看出来Service层直接持有了Dao层的对象,Service层与Dao层太紧了。

那么三层中的UserServcie类就是命令模式中的:Invoker 这个角色
UserDao类就是命令模式中的:Receiver 这个角色
getUser这个操作就可以用来Command对象来表示

所以我们就可以使用命令模式进行UserService(方法的请求者Invoker )与UserDao(方法的实现者Receiver)直接的解耦。同时我们也发现了命令模式的缺点:类数量增加了,如果你UserDao有很多操作,那么Command类的数量就爆炸了。。。
ps:个人认为,这样描述比用各种新名词,各种示例又是厨子、又是做饭、又是顾客的各种打比方好理解多了,因为service、dao都是我们所熟悉的东西,不用任何抽象。但是大家还是要知道命令模式中名词的,比喻只是为了更好的理解

使用命令模式实现三层架构的解耦

我们使用命令模式实现三层架构的解耦
增加 Command 抽象类

public abstract class Command
{
	public object execute();
}

增加GetUserCommand类(Command的实现类)
GetUserCommand 类现在持有了UserDao的引用,它用来执行真正的getUser操作

public class GetUserCommand : Command
{
	UserDao userDao;
	public GetUserCommand()
	{
		userDao = new UserDao();
	}
	public override object execute()
	{
		return userDao.getUser();
	}
}

修改UserService类

//业务逻辑层
public class UserService 
{
	Command getUserCommand = new GetUserCommand();
	
	public User getUser(){
		return getUserCommand.execute() as User;
	}
}

好了,UserService和UserDao的耦合就此断开,以后如果我们要更换Dao的getUser方法,只需要改动GetUserCommand就行了,与Service层毛关系都没有(如果Service层有很多地方使用了GetUser方法,不解耦的话就需要改动很多地方)。
以上是理想状态,只是为了演示命令模式的解耦功能。
UserDao和UserService里不可能只有这么一个方法,Command在Service中如何保存也是个问题(可以用hash表存储),以及什么时候去创建Command,如何调用对应的Command等等。。。这些不在本文讨论范围。

到这里可以看到我们把Dao和Service的耦合断开了,同时我们也看到Service增加了新的依赖:Command相关类,我们把getUser这个操作变成了一个Command对象。

彩蛋

说到解耦,我认为没有绝对的解耦,只不过是从直接依赖变成了间接依赖。完全解耦??不可能,难道用量子来交流?
以上是个人理解,如果大家有不同意见。我不听,我不听,我不听,拜拜!咱们江湖再见!(欢迎大家评论区留言)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值