java 欢迎进入设计模式世界之前凑

现在工作不忙,买了本head first 设计模式的书看看,看着想睡觉,所以想以博客的形式分享出来,可能写的不好,毕竟我也是刚学,但没关系,希望大家在发现错误的时候能改正,技术在于分享,设计模式虽然不是什么高深的技术,但是要在实际的项目中玩的很溜也不容易啊 ,在很多好点的开源项目中都用到了设计模式,所以学好设计模式很重要,本人也是菜鸟一枚希望和大家一起进步 ,发大财!努力学习模式吧,骚年!

引入:

Joe上班的公司做了一套相当成功的模拟鸭子游戏:SimUDuck.游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统的内部设计使用了标准的oo(面向对象)技术,设计了一个鸭子超类(superclass),并让各种鸭子继承此超类。

分析:每个鸭子都有其共同的特点,而也有不同之处,所以我们得设计一个类把共同的特点抽取出来,而不同之处让其每个鸭子自己去实现,在java中也是让每个子类自己去实现,共同的特点就是鸭子会游泳,会呱呱叫,而不同点在于每个鸭子的外观是不一样的,在这我们把鸭子的超类命名为Duck,他里面有quck(呱呱叫方法),swim(游泳方法),display(鸭子外观显示方法,是一个抽象方法,因为每个鸭子外观都不一样)

代码:

Duck

public abstract class Duck {public void quack(){}public void swim(){}public abstract void display();}有二个子类MallardDuck,RedheadDuck继承了Duck,

MallardDuck.java:

package cn.kge.pattern1;/** * MallardDuck继承了抽象类Duck * 复写了抽象类中的抽象方法 display */public class MallardDuck extends Duck {@Overridepublic void display() {System.out.println(" MallardDuck——display ");}}RedheadDuck.java

package cn.kge.pattern1;public class RedheadDuck extends Duck {@Overridepublic void display() {System.out.println(" RedheadDuck——display ");}}可能你还会暗暗得意,这系统或者框架设计的很牛逼,突然一天你boss说,码农此模拟程序需要会飞的鸭子,这个时候你很得意的在boss面前说这个一天搞定,只要在Duck(抽象类中添加一个fly)方法即可,

Duck.java

package cn.kge.pattern1;public abstract class Duck {public void quack(){}public void swim(){}public void fly(){}public abstract void display();}而其他子类只能复写fly()方法即可,这个需求就搞定了,如果这个时候被老板看到你这么写的话,估计你就准备投简历找工作了,难道我一个玩具鸭子也会飞,于是乎你就思考人生吧,如果直接在父类(Duck)中添加了fly方法,那么那些(像玩具鸭子)也会具有飞的行为,那么这肯定是不符合逻辑的,虽然你只是在父类中添加了一个方法,但是这会导致其他继承他的子类都会具有的行为,这就是对代码所做的局部修改,影响层面可不只是局部。这个时候码农深深的体会到了一件事,

为了复用的目的而使用继承结局并不完美,如果这个系统越大越难维护,请不要叫我码农,请叫我工程师,因为我会改bug,改方案!这就是像我这样屌丝工程师存在的价值,这个时候我们就不要使用继承了,就使用接口就行了,如果那个鸭子需要飞这个行为,就实现这个接口,而不需要的就不要实现这个接口就行,如果这个时候有哦个诱饵鸭,它不会飞也不会叫,那么这个时候我们继承父类的quack和swim方法 就什么都不用写了,也就是在方法中没有具体的业务逻辑代码了,写在这里不是多余么,而且还不方便后期人员读懂代码,而使用接口会造成代码无法复用,每个鸭子都要重写一篇一样的代码,这肯定是要重构的,所以使用接口也有它的缺点所在,

问题总结:现在我们知道使用继承并不能很好地解决问题,因为鸭子的行为在子类里不断地改变,并且让所有的子类都有这些行为是不恰当的,Flyable与Quackable接口一开始视乎还挺不错,解决了问题,但是java接口不具备实现代码,所有继承接口无法达到代码的复用,这就意味着:无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中修改它,一不小心可能会造成新的错误! 幸运的是,有一个设计原则,恰好使用这个状况,

设计原则之一:

找出应用中可能需要变化之外,把它们独立出来,不要和那些不需要变化的代码混在一起。

分开变化和不会变化的部分

但是我们从哪开始呢?就我们目前所知,除了fly()和quack()的问题之外,Duck类还算一切正常,似乎没有特别需要经常变化或者修改的地方,所以,除了某些小改变之外,我们不打算对Duck类做太多处理,

现在,为了要分开"变化和不会变化的部分",我们准备建立二组类(完全远离Duck类),一个是"fly"相关的,一个时"quack”相关的,每一组类将实行各自的工作,比方说,我们可能有一个实现"呱呱叫",另一个类实现"吱吱叫",还有一个类实现"安静",

我们知道Duck类内的fly()和quack()会随着鸭子的不同而改变.

为了要把这二个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为

设计鸭子的行为

如何设计那组实现飞行和呱呱叫的行为类呢?

但是设计出来的要有后期的可维护性和可扩展性,比方说,我们想要产生一个新的绿头鸭实例,并指定特定"类型"的飞行行为给它,顺便让鸭子的行为可以动态地改变好了,换句话说,我们应该在鸭子类中包含设定行为的方法,这样就可以在"运行时"动态地"改变"绿头鸭的飞行行为,

有了这些目标要实现,我们就要看看设计原则的第二个设计原则:

针对接口编程,而不是针对实现编程!

在java中行为都是动词,表示类的行为,而在java中对应的是方法,我们利用接口代表每个行为,比方说,FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中的一个接口,

针对接口编程含义:

一个人的期望值越大,心理承受力就会越小,就越经受不住失败的打击,

java 欢迎进入设计模式世界之前凑

相关文章:

你感兴趣的文章:

标签云: