共计 7799 个字符,预计需要花费 20 分钟才能阅读完成。
简介:
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;
}
}
完结:代码比拟丑,前期重构之后再来改良
正文完