对像我一样正在学习java的人来讲,对设计模式的学习是个很重要的环节。而我们在学习设计模式时,不仅仅应该知道它们的思想,还要学会将设计模式与实际开发中需要解决的具体问题相联系,这是成为一名优秀程序员的很重要的一点。
大多数玩游戏的我们都应该玩过“*飞车”这款游戏,对于游戏中的各种效果和功能,我想把它们结合到我们学习的设计模式中来。
首先说说我们在IO流中学到的装饰模式:
在玩“*飞车”这款游戏,游戏中有对汽车进行喷涂鸦的功能,而且这个喷涂鸦是可以覆盖的,并且覆盖的顺序也影响到最后车身的显示效果,假设现在喷涂鸦具有2种样式:(1)红色火焰 (2)紫色霞光。
装饰模式代码:
新建一个抽象汽车父类:
package car_package; public abstract class car_parent { // 汽车抽象父类 private String make_address; private int speed; public String getMake_address() { return make_address; } public void setMake_address(String make_address) { this.make_address = make_address; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public abstract void print_face(); } |
然后新建一个奥迪汽车子类
package car_package; public class audi_sub extends car_parent { // 奥迪汽车子类 @Override public void print_face() { System.out.println("audi车默认的颜色为 黑色"); } } |
然后再新建一个装饰者父类:
package decorator_package; import car_package.car_parent; public abstract class decorator_parent extends car_parent { // 装饰者父类 protected car_parent car_parent_ref; public void setCar_parent_ref(car_parent car_parent_ref) { this.car_parent_ref = car_parent_ref; } @Override public void print_face() { car_parent_ref.print_face(); } } |
然后再新建装饰者子类:红色火焰装饰者类:
package decorator_package; public class decorator_audi_red extends decorator_parent { @Override public void print_face() { super.print_face(); System.out.println("给 奥迪 喷涂鸦 - 颜色为 红色火焰"); } } |
然后再新建装饰者子类:紫色霞光装饰者类:
package decorator_package; public class decorator_audi_purple extends decorator_parent { @Override public void print_face() { super.print_face(); System.out.println("给 奥迪 喷涂鸦 - 颜色为 紫色霞光"); } } |
新建一个运行类
package main_run; import car_package.audi_sub; import decorator_package.decorator_audi_purple; import decorator_package.decorator_audi_red; public class main_run { public static void main(String[] args) { audi_sub audi_sub_ref = new audi_sub(); audi_sub_ref.setMake_address("北京市朝阳区"); audi_sub_ref.setSpeed(200); decorator_audi_red decorator_audi_red_ref = new decorator_audi_red(); decorator_audi_red_ref.setCar_parent_ref(audi_sub_ref); decorator_audi_purple decorator_audi_purple_ref = new decorator_audi_purple(); decorator_audi_purple_ref.setCar_parent_ref(decorator_audi_red_ref); decorator_audi_purple_ref.print_face(); } } |
程序运行结果如下:
audi车默认的颜色为 黑色 给 奥迪 喷涂鸦 - 颜色为 红色火焰 给 奥迪 喷涂鸦 - 颜色为 紫色霞光 |
再讲讲高新技术里提到的代理模式:
在玩“*飞车”这款游戏,如果游戏者手中的金钱达到了一定的数量就可以到车店买一部性能更高的赛车,那么这个卖车的“车店”就是一个典型的“汽车厂家”的“代理”,他为汽车厂家“提供卖车的服务”给有需求的人士。从面向对象的方面考虑,“销售汽车的代理”也是一个对象,那么这个对象也具有一定的状态,在软件项目中这个对象也具有管理财务进销存的基本功能,那么在设计时就要以面向OOP编程的思想来考虑软件的类结构,这个销售汽车的代理也是一个类了。
代理模式代码:
新建一个买车的接口:
package buy_car_package; public interface buy_car_package { public void buy_car(); } |
新建一个people人类,具有买车的行为,所以实现接口buy_car_package:
package buy_car_imple; import buy_car_package.buy_car_package; public class people implements buy_car_package { private int cash; private String username; public int getCash() { return cash; } public void setCash(int cash) { this.cash = cash; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public void buy_car() { System.out.println(username + "买了一台新车"); } } |
people类不能拥有车,必须经过proxy代理类的认证,符合条件之后才可以拥有车辆,新建一个代理,这个代理类来考察当前的people是否有资格进行买车:
package buy_car_imple; import buy_car_package.buy_car_package; public class proxy_buy_car_imple implements buy_car_package { private people people; public people getPeople() { return people; } public void setPeople(people people) { this.people = people; } public void buy_car() { if (people.getCash() > 3000) { System.out.println(people.getUsername() + "花" + people.getCash() + "块 买了新车 交易结束"); } else { System.out.println(people.getUsername() + "金钱不够,请继续比赛!"); } } } |
最后创建一个客户端,用来模拟买车的行为:
package run_main; import buy_car_imple.people; import buy_car_imple.proxy_buy_car_imple; public class run_main { public static void main(String[] args) { people people_ref1 = new people(); people_ref1.setCash(4000); people_ref1.setUsername("黑马学员"); people people_ref2 = new people(); people_ref2.setCash(2000); people_ref2.setUsername("java冬冬"); proxy_buy_car_imple proxy_buy_car_imple = new proxy_buy_car_imple(); proxy_buy_car_imple.setPeople(people_ref1); proxy_buy_car_imple.buy_car(); proxy_buy_car_imple.setPeople(people_ref2); proxy_buy_car_imple.buy_car(); } } |
程序运行结果如下:
黑马学员花4000块 买了新车 交易结束 java冬冬金钱不够,请继续比赛! |
这样people就不可能*的拥有车辆,必须经过proxy的认证之后才可以。
而代理模式在GOF*的介绍中大体有4种使用情景:
(1)远程代理。典型的就是客户端与webservice使用的情况,客户端由于是针对OOP编程,而不是针对webservice中的方法进行编程,所以得在客户端模拟一下webservice的环境,用proxy来对webservice进行包装,这样就可以使用proxy代理类来远程操作webservice了。
(2)虚拟代理。比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。
(3)安全代理。其实也就是本例中所举的买车的例子,金钱不够不可以买车!
(4)智能指引。比如在访问一个对象时检测其是否被锁定等情况。
再说一下模板方法模式:
在玩“*飞车”这款游戏,每辆车都有显示速度的仪表盘,但有可能A车显示的是蓝色的仪表盘,B车显示的是红色的仪表盘,分析中可以发现,他们都有车速度的值,但显示的方式不太一样。其实模板方法就是最典型的“继承”的使用,大家平时百分百都可以用到,只是不知道叫模板方法模式:)!
模板方法模式代码:
新建赛车的父类:
package car_package; public class car_parent { private int speed; public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public void print_speed() { System.out.println("将速度" + this.getSpeed() + "取出来!"); } } |
新建红色仪表盘的赛车实现类:
package car_imple; import car_package.car_parent; public class car_imple_red extends car_parent { @Override public void print_speed() { super.print_speed(); System.out.println("将速度" + this.getSpeed() + "用红色的仪表盘显示车的速度"); } } |
新建蓝色仪表盘的赛车实现类:
package car_imple; import car_package.car_parent; public class car_imple_blue extends car_parent { @Override public void print_speed() { super.print_speed(); System.out.println("将速度" + this.getSpeed() + "用蓝色的仪表盘显示车的速度"); } } |
新建客户端运行类:
package run_main; import car_imple.car_imple_blue; import car_imple.car_imple_red; import car_package.car_parent; public class run_main { public static void main(String[] args) { car_parent car_ref_red = new car_imple_red(); car_ref_red.setSpeed(300); car_ref_red.print_speed(); car_parent car_ref_blue = new car_imple_blue(); car_ref_blue.setSpeed(400); car_ref_blue.print_speed(); } } |
程序运行结果如下:
将速度300取出来! 将速度300用红色的仪表盘显示车的速度 将速度400取出来! 将速度400用蓝色的仪表盘显示车的速度 |
这就是模板方法模式,一个最常用,最容易理解的一个模式,将相同的功能抽象出来成一个父类,然后用子类做不同功能的实现。