软考看了不少的设计模式,越向后看越有感觉,特此来分享一下。
一、对于模式的理解
对于设计模式,相信大家都有了不少的理解,那么再次学习设计模式大家有没有注意到设计模式中对于功能的扩展以及对于变化的类的使用是否有了新的了解呢?
其实对于设计模式最大的作用莫过于对于各种现实各种问题所涉及到的类的扩展以及类之间的解耦和,还有对于抽象和对象的深度引用,把面向对象的编程发挥的淋漓尽致。不知道同学们有没有发现几乎所有关于扩展类的地方都可以从以下几个地方来实现:
1、抽象类的多个继承。
2、接口的多个实现实现。
3、对于组合的运用产生实现不同的功能类。
对于前两种大家见的可能比较多了,但是最后一种是什么呢,详细的实例请见桥接模式,继承就不用说了,组合的运用会让我们在用设计模式的时候可以随意组合桥接的类来生成新的我们想要的类。看着HeadFirst就更加可以明白这其中的意思了,只要把故事看完,就会发现里面的问题从开始的解决方案到最后的解决方案都是我们在不断的模式化的过程中所走过的路程。
二、对于扩展后的调用的理解
我们都知道设计模式是为了解耦和,添加可扩展而生的,但是怎么体现这个东西呢,继承扩展之后又是怎么进行使用的呢,这里为大家说明一下。
在设计模式中几乎都是要被上层调用才会发挥作用的,归根到底设计模式很好的实现了面向修改封闭,面向扩展开放的开放-封闭原则,因为在这里我们看到几乎里面的扩展是以继承的形式或者添加实现的方式来实现的,所以原来的类基本都是不用改的,需要修改的仅仅是调用而已。
上层的调用就是模式中所给的客户端(Client)对于这里的客户端的代码我们给一个例子:
如上图为命令模式的UML图,里面就有一个Client类,写了这个方法的调用和类的选择,其中里面的接口是可以有多重实现来扩展功能的,这里讲的就是对于客户端是怎样选择实现的。有的设计模式可能没有写Client端,这样也不影响,因为使用的时候是嵌套在上层调用中的。
代码就不全写出来了,只写一下部分代码:
调用端:
Receiver r = new Receiver(); //接收者
Command c = new ConcreteCommand(r); //给接口指定具体的实现并指定接受者
Invoker i = new Invoker(); //命令的执行对象
// Set and execute command
i.SetCommand(c); //指定具体实现对象
i.ExecuteCommand(); //执行具体命令
Console.Read(); //停止在结果界面(实为等待输入)
这里我们看到第二行就是具体的接口的实现指定,这里也可以换为抽象工厂的注入控制,更加的解耦。另外这个里面所有的执行和命令载入都是在客户端实现的,所以如果想换命令的执行者和命令本身的话可以添加实现类和实施的命令类从而扩展方法,而原代码的改变只有客户端。
命令抽象类:
abstract class Command
{
protected Receiver receiver; //定义私有属性对象
public Command(Receiver receiver) //构造函数这里就是定义的关键,可以随时传入新的用来做新的实现
{
this.receiver = receiver;
}
abstract public void Execute();
}
执行对象类:
class Invoker
{
private Command command; //定义私有属性命令对象
public void SetCommand(Command command) //定义选择实现具体的命令对象,这里也是关键,可以进行灵活的配置
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
如上面两个类中使用的先定义一个私有的属性对象然后再通过方法传入相应的实现对象这里很是重要,因为有许多模式都是用这里的特点来作的传递和实现,因为这里是灵活可配的,所以这里颇为有用,这也为了灵活扩展打下了基础。
不知道大家是否还记得里氏代换原则,子类和父类可以替换的方法在这里体现的淋漓尽致。所以这些原则也是我们要学习和理解的关键。
三、总结
设计模式需要我们理解的还有很多,但是只要记住思想的核心,然后结合思想来看代码是怎么实现的,然后再思考如何扩展,就可以把设计模式理解的很清楚了。