走下神坛的设计模式--设计模式入门(2)

各位读者发现原来设计模式这么简单。模式源于软件工程师实践中的经验,对于经历过各种软件开发梦魇的工程师来说,很多模式一看就懂,可是对于开发经验不是很多的初学者,有些模式还着实费解。下面就创建模式的其他方法,再来谈谈。 



静态工厂方法确实很简单,想法也比较直接,一般开发者很自然就会用到。但是对于产品多一点的,难道每次增加一个产品都去改代码,在 if else  里添加代码?那也是挺烦的。曾有看过一个朋友的代码,if else里嵌套了3000行代码,并且其中还有很多层if else,看得我差点把显示器砸了。所以还得想点别的办法。if else 是用来干啥的,呵呵,用来表示逻辑,变化的。用个高深的名词,那叫多态。处理多态,用if else 比较直接,但是也比较低级。逻辑多了,就容易让人发昏。尤其是修改别人代码,增加功能的时候,简直是噩梦。那么处理多态,有没有更好的办法呢,有啊,通过继承,通过委托,都可以实现多态。--设计模式基本上就是解决多态的问题的。 



在开讲之前,还得先普及点面向对象的知识。面向对象?谁不知道阿,就是一些 class了。这些class可以实现数据封装,继承,抽象,多态,等等。呵呵,说起来是挺简单,可别小瞧了这几个字,里面大有学问。先说封装,封装不仅仅意味着把数据定义在类中,只通过getter/setter存取,广义的封装还意味着,你的类应该在满足要求的情况下,提供最小的接口,越少,越简单也好,为啥?这样,你的类才容易使用,别人才不容易范错,并且你要改动时,对别人的影响才最小。就当使用你的类的人是个超级大傻瓜好了。好了,我们有了一个傻瓜原则。继承呢,很好理解了,就是子类继承父类后,父类的方法子类都可以用了,呵呵,这样可以少些好多代码阿,应该大力提倡!奇怪,为什么大师们都说要少用继承呢?继承是一个静态关系,一定下来,就没法改了,(谁还能选择自己的父母么?)但是分类的方法有很多种,很快你就会发现以前的继承有点问题,可是不能改了,怎么办?没着了,要是能够动态换父母那还了得?!所以呢,继承要少用,如果不是很确定,还是使用组合的方式,就是把你原来想继承的类,当作新类的内部属性,然后把需要的方法包装一下,代码比原来多点,但是灵活阿。现在新类和旧类的关系是朋友而不是父子了,那天不喜欢,换一个就是,这里可没人管你对朋友忠诚不忠诚,呵呵。抽象是啥意思呢,其实抽象和多态是一体的,多态可以通过继承实现,也可以通过组合的方式实现。不是我不明白,这世界变化快。因为变化太多了,所以描述一个事物呢,尽量不要太具体了,而是尽量把事物的共性抽出来,抽象出一个模型,而事物的具体,让多态去实现。现代对象设计的一个思想就是用继承来实现多态,而不是用他来实现子类的扩展。这样,子类就不对父类的接口进行扩展了。也就可以面向接口编程了。理想的面向接口编程,应该是客户端只能看到接口,而看不到具体的子类,但是接口是不能被实例化的,实例化的只能是具体类。客户端看不到子类也就不可能自己去实例化一个具体类,所以也就只好靠工厂方法来创建具体的类了。还看过一个朋友的程序,那位朋友接受了面象接口的概念,所有的类都是先定义一个接口,然后在别的地方实现,这挺好啊,可是这位哥们懒得去定义工厂方法,他的前端程序里,一会是接口,一会是具体的类,搞得人晕头转向。如果要修改的话,不知道要改多少地方,这样的面向接口编程还有什么意义。所以如果你定义了一堆接口,可能的话,就让客户端只看到你的接口,而看不到具体的类。这样具体的类才可能实现可替换性。这也符合傻瓜原则,呵呵。 



越谈越远了,上面说了那么多,归根结底就是面向接口编程,用多态来实现变化的部分,和用工厂实例化具体类。 



面向接口的编程离不开工厂方法,但是静态工厂方法因为用一个工厂来生产多种产品,产品太多的时候,管理比较乱,所以应该改进一下。怎么改进呢,想想生产线上的工人,每人只做自己的一点工作,别的事不管。这种方法可以借鉴。据说提高效率的最好办法是分工协作,让一个人做太多事既不公平,也容易出错,效率也低。所以呢,分工!怎么分呢,首先这个工厂生产的产品都是相近的,比如都是螺丝帽,要造轮胎你就找别人吧。这样产品才会有共性,把这个共性抽出来,作为一个接口,不同产品就共享这个接口。下面是工厂方法的一些具体实现方式。 





1.最原始最简单的工厂方法。

可能只有一个工厂生产全部产品,也可能按照一定的分类关系,由若干个工厂生产产品,每个工厂生产相关产品。



public class MyFactory()

{

Product1 getProduct1(){}

Product2 getProduct2(){}







因为Product1和Product2之间没有太多共性,所以共享一个接口意义不大,因此还是分成不同方法比较好。但是产品之间一般还是有一定关联。也就是工厂生产的是一些相关产品。如螺丝和螺母。如果要轮胎,还是另建一个工厂比较好。 





2.高级点的简单工厂

每种产品都由同一个工厂产生,并且产品之间比较相近,可以共享接口。比如生产不同规格的螺丝。虽然不同规格,但是螺丝有些共性。

interface 螺钉()

{

get长度();

get直径(); 







class 十字螺钉() implements 螺钉

{

get长度(){...};

get直径(){...};





class 一字螺钉() implements 螺钉

{

get长度(){...};

get直径(){...};





public class 螺钉工厂()

{

螺钉 get螺钉(String 螺钉类型)

{

if(螺钉类型.equals("十字螺钉"))

return new 十字螺钉();

else if(螺钉类型.equals("一字螺钉"))

return new 一字螺钉();

}





3.典型的工厂方法

对于上面实现,如果现在又有了一个6边形螺钉怎么办,当然你可以在get螺钉()方法中再增加一个else if语句,但是这样需要修改原来代码的方式是不太好的,容易出错。有些时候,甚至你根本没有源代码,怎么办呢?还记得前面说的,尽量不修改已有代码么?办法还是有的,用继承啊。对于每个产品都创建一个工厂,然后用这个工厂创建产品。不用修改原来代码,只是增加代码。这就是典型的工厂方法了。 



inteface 螺钉()

{

get长度();

get直径(); 







interface 螺钉工厂()

{

螺钉 get螺钉();





class 十字螺钉() implements 螺钉

{

get长度(){...};

get直径(){...};





class 一字螺钉() implements 螺钉

{

get长度(){...};

get直径(){...};





class 6边螺钉() implements 螺钉

{

get长度(){...};

get直径(){...};







public class 十字螺钉工厂 implements 螺钉工厂()

{

螺钉 get螺钉()

{

return new 十字螺钉();

}





public class 一字螺钉工厂 implements 螺钉工厂()

{

螺钉 get螺钉()

{

return new 一字螺钉();

}

}

public class 6边螺钉工厂 implements 螺钉工厂()

{

螺钉 get螺钉()

{

return new 6边螺钉();

}







4.原型模式

还有一种情况下,你已经获得了一个产品,这个产品是一个接口而不是具体类。--你获得的方式肯定是通过某种工厂方法,或者是个参数。比如你只知道他是螺丁,不知道是十字的,还是一字的。现在你需要一个同样的螺钉,怎么办? 你不知道他的具体类是什么,也不知道要用哪个工厂方法去产生。这时可以通过克隆的方式。对于java来说,克隆是比较简单的,已经内置到Object中了。当然根据需要,你可能要改写几个方法。这就不详谈了。 



另外,根据GOF的说法,java的反射机制也是一种克隆方法。不过不是通过对象的克隆,而是通过类定义的方式。还记得最开始的jdbc的例子么?现在知道他既是个简单工厂,又是个克隆方法。同理螺钉的例子,工厂可以简化成 



public class 螺钉工厂()

{

螺钉 get螺钉(String 螺钉类型)

{

return (螺钉)(Class.forName(螺钉类型).newInstance()); 







但是用这种方式要小心,如果某种螺钉类型你根本没实现,或者实现的不是螺钉接口,是会出错的。你应该判断这些情况,并抛出异常。 

你可能感兴趣的:(计算机技术,设计模式,产品,class,编程,interface,string)