简介:
1、门面模式(facade)
门面模式:比方政府部门,你须要提交一些材料证实你本人是你本人,可能会从这个部门跑到那个部门,串来串去都办不好,然而如果有一个部门来对立协调这些部门之间的关系,而你只须要找到这个对立的部门来解决问题就能够了,效率就高了,这个就是所谓的门面模式。
2、调停者模式(Mediator)
调停者模式:下面所说的门面,其实也能够作为调停者,它对外来说是门面,而对外部的部门来说,他就是调停者,由它来协调部门之间的关系,各个部门只须要与这个调解部门分割,而相互之间不须要再有分割了,这就是所谓的调停者模式。
如下:咱们举个例子,我写了一个坦克大战这个小游戏,游戏物体有坦克,子弹(临时只有这两个),墙,碉堡等,咱们每一个游戏物体都须要解决本人与其余游戏物体的关系,如:坦克与子弹相撞,坦克与墙相撞,坦克与坦克相撞,子弹与墙相撞,子弹与坦克相撞,子弹与碉堡相撞等等,每个物体都要与其余的物体分割,如果后续再退出其余的游戏物体,那么后面的每个物体都须要批改,能不能想个办法让他们不要有那么简单的分割。
模式实例:
1、GameObject:游戏物体父类
package com.mashibing.tank;import java.awt.*;/** * 游戏物体的父类,无论是坦克,子弹,爆炸等等都继承自这个类 */public abstract class GameObject { public int x, y; public abstract void paint(Graphics g);}
2、Tank:坦克类
package com.mashibing.tank;import com.mashibing.strategy.FireStrategy;import java.awt.*;import java.util.Random;public class Tank extends GameObject{ public Dir dir = Dir.DOWN; private static final int SPEED = ProperMgr.getInt("tankSpeed"); private boolean moving = true; public GameModel gm = null; public static int WIDTH = ResourceMgr.goodTankU.getWidth(); public static int HEIGHT = ResourceMgr.goodTankU.getHeight(); private boolean living = true; public FireStrategy fs; public Group group = Group.BAD; public Rectangle rect = new Rectangle(); private Random random = new Random(); public int oldX, oldY; public Tank(int x, int y, Dir dir, Group group, GameModel gm) { this.x = x; this.y = y; this.dir = dir; this.gm = gm; this.group = group; rect.x = this.x; rect.y = this.y; rect.width = WIDTH; rect.height = HEIGHT; try { if(group == Group.GOOD){ String goodFsName = ProperMgr.get("goodFs").toString(); fs = (FireStrategy)Class.forName(goodFsName).getDeclaredConstructor().newInstance(); // 指定构造函数,进行对象的结构 } else { String goodFsName = ProperMgr.get("badFs").toString(); fs = (FireStrategy)Class.forName(goodFsName).newInstance();//必须得有一个默认的空构造函数进行结构 } } catch (Exception e) { e.printStackTrace(); } } @Override public void paint(Graphics g) { if (!living) gm.remove(this); Color c = g.getColor(); switch (dir) { case LEFT: g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankL : ResourceMgr.badTankL,x,y,null); break; case UP: g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankU : ResourceMgr.badTankU,x,y,null); break; case RIGHT: g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankR : ResourceMgr.badTankR,x,y,null); break; case DOWN: g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankD : ResourceMgr.badTankD,x,y,null); break; } move(); } private void move() { oldX = x; oldY = y; if (!moving) return; switch (dir) { case LEFT: x -= SPEED; break; case UP: y -= SPEED; break; case RIGHT: x += SPEED; break; case DOWN: y += SPEED; break; } if(this.group == Group.BAD && random.nextInt(100)>95) { this.fire(); } if (this.group == Group.BAD && random.nextInt(100)>95) randomDir(); //边界检测 boundsCheck(); rect.x = this.x; rect.y = this.y; } private void boundsCheck() { if(this.x < 2) x = 0; if(this.y < 28) y = 30; if(this.x > TankFrame.GAME_WIDTH - Tank.WIDTH-2) x = TankFrame.GAME_WIDTH-Tank.WIDTH-2; if(this.y > TankFrame.GAME_HEIGHT - Tank.HEIGHT-2) y = TankFrame.GAME_HEIGHT-Tank.HEIGHT-2; } private void randomDir() { this.dir = Dir.values()[random.nextInt(4)]; } public void fire() { fs.fire(this); } public void die() { this.living = false; } public void stop(){ moving = false; } public void setDir(Dir dir) { this.dir = dir; } public static int getSPEED() { return SPEED; } public void setMoving(boolean moving) { this.moving = moving; } public void setGroup(Group group) { this.group = group; }}
3、Bullet:子弹类
package com.mashibing.tank;import java.awt.*;public class Bullet extends GameObject{ private static final int SPEED = ProperMgr.getInt("bulletSpeed"); public Rectangle rect = new Rectangle(); private Dir dir; public static int WIDTH = ResourceMgr.bulletD.getWidth(); public static int HEIGHT = ResourceMgr.bulletD.getHeight(); private boolean living = true; //子弹是否死掉,飞出窗口或者撞到敌人 public GameModel gm = null; public Group group = Group.BAD; public Bullet(int x, int y, Dir dir, Group group, GameModel gm) { this.x = x; this.y = y; this.dir = dir; this.gm = gm; this.group = group; rect.x = this.x; rect.y = this.y; rect.width = WIDTH; rect.height = HEIGHT; gm.add(this); } @Override public void paint(Graphics g) { if(!living){ gm.remove(this); } switch (dir) { case LEFT: g.drawImage(ResourceMgr.bulletL,x,y,null); break; case UP: g.drawImage(ResourceMgr.bulletU,x,y,null); break; case RIGHT: g.drawImage(ResourceMgr.bulletR,x,y,null); break; case DOWN: g.drawImage(ResourceMgr.bulletD,x,y,null); break; } move(); } private void move() { switch (dir) { case LEFT: x -= SPEED; break; case UP: y -= SPEED; break; case RIGHT: x += SPEED; break; case DOWN: y += SPEED; break; } rect.x = this.x; rect.y = this.y; if (x < 0 || y < 0 || x > TankFrame.GAME_WIDTH || y > TankFrame.GAME_HEIGHT) living = false; } public void die() { this.living = false; }}
4、Bullet:爆炸类
package com.mashibing.tank;import java.awt.*;public class Explode extends GameObject{ public static int WIDTH = ResourceMgr.explodes[0].getWidth(); public static int HEIGHT = ResourceMgr.explodes[0].getHeight(); private GameModel gm = null; private int step = 0; public Explode(int x, int y,GameModel gm) { this.x = x; this.y = y; this.gm = gm; } @Override public void paint(Graphics g) { g.drawImage(ResourceMgr.explodes[step++],x,y,null); if(step >= ResourceMgr.explodes.length) { gm.remove(this); } }}
5、GameModel:调停者/门面
package com.mashibing.tank;import com.mashibing.cor.ColliderChain;import java.awt.*;import java.util.ArrayList;import java.util.List;/** * 负责游戏物体之间的逻辑解决,也就是所谓的门面模式, * 它提供一系列接口供TankFrame调用, * 也是个调停者模式,它解决了游戏物体之间的碰撞,各种游戏物体的碰撞都通过本类 * 中的碰撞检测去实现与其余物体的碰撞,而不是在游戏物体的类当中去解决具体的碰撞逻辑 * * 也就是说以前呢子弹与坦克的碰撞逻辑在Bullet中去实现,如果当前退出了其余的游戏物体须要与子弹碰撞 * 那么子弹类中的碰撞逻辑就须要批改,而当初在本类当中解决碰撞,只需提供相应的碰撞策略(Collider)就能够实现 */public class GameModel { //我方坦克 public Tank myTank = new Tank(200,500, Dir.UP, Group.GOOD, this); //游戏物体:敌方坦克,子弹,爆炸 private List<GameObject> objects = new ArrayList<>(); //碰撞检测责任链 ColliderChain chain = new ColliderChain(); public GameModel(){ //初始化敌方坦克 int initTankCount = ProperMgr.getInt("initTankCount"); for(int i = 0; i < initTankCount; i++) { add(new Tank(50+i*80, 200, Dir.DOWN, Group.BAD, this)); } } public void add(GameObject go){ this.objects.add(go); } public void remove(GameObject go){ this.objects.remove(go); } public void paint(Graphics g) { Color c = g.getColor(); g.setColor(Color.white); g.setColor(c); myTank.paint(g); for(int i = 0; i < objects.size(); i++) { objects.get(i).paint(g); } //碰撞检测 for(int i = 0; i < objects.size(); i++) { for(int j = i+1; j < objects.size(); j++){ GameObject o1 = objects.get(i); GameObject o2 = objects.get(j); chain.collide(o1, o2); } } } public Tank getMyTank() { return myTank; }}
6、Collider:碰撞解决接口
package com.mashibing.cor;import com.mashibing.tank.GameObject;public interface Collider { boolean collide(GameObject o1, GameObject o2);}
7、BulletTankCollider:子弹与坦克的碰撞策略
package com.mashibing.cor;import com.mashibing.tank.Bullet;import com.mashibing.tank.Explode;import com.mashibing.tank.GameObject;import com.mashibing.tank.Tank;public class BulletTankCollider implements Collider{ @Override public boolean collide(GameObject o1, GameObject o2) { if(o1 instanceof Bullet && o2 instanceof Tank) { Bullet b = (Bullet) o1; Tank t = (Tank) o2; if(b.group == t.group) return false; if(b.rect.intersects(t.rect)) { t.die(); b.die(); int ex = t.x + Tank.WIDTH / 2 - Explode.WIDTH / 2; int ey = t.y + Tank.HEIGHT / 2 - Explode.HEIGHT / 2; b.gm.add(new Explode(ex, ey, b.gm)); return false; } } else if(o1 instanceof Tank && o2 instanceof Bullet){ return collide(o2, o1); } return true; }}
8、TankTankCollider:坦克与坦克的碰撞策略
package com.mashibing.cor;import com.mashibing.tank.GameObject;import com.mashibing.tank.Tank;public class TankTankCollider implements Collider{ @Override public boolean collide(GameObject o1, GameObject o2) { if(o1 instanceof Tank && o2 instanceof Tank) { Tank t1 = (Tank) o1; Tank t2 = (Tank) o2; if(t1.rect.intersects(t2.rect)) { t1.x = t1.oldX; t1.y = t1.oldY; t2.x = t2.oldX; t2.y = t2.oldY; } } return true; }}
9、ColliderChain:碰撞链:此处将碰撞的这些策略,连在一起(也就是装在一个汇合当中),当一个物体检测本人与其余物体的碰撞时,将链条当中的碰撞策略都检测一遍即可(也就是循环一便)
package com.mashibing.cor;import com.mashibing.tank.GameObject;import java.util.LinkedList;import java.util.List;public class ColliderChain implements Collider{ private List<Collider> colliders = new LinkedList<>(); public void add(Collider c){ colliders.add(c); } //默认退出这两种碰撞策略,后续如有须要便往里面增加,也能够在配置文件外面配置碰撞策略,结构链条的时候读取配置文件而后加进colliders外面 public ColliderChain(){ add(new BulletTankCollider()); add(new TankTankCollider()); } public boolean collide(GameObject o1, GameObject o2) { for(int i = 0; i<colliders.size(); i++){ if(!colliders.get(i).collide(o1, o2)){ return false; } } return true; }}
完结:代码比拟丑,前期重构之后再来改良