ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

装饰器模式(Decorator)

2021-09-20 11:33:42  阅读:141  来源: 互联网

标签:int GameObject 模式 public go import 装饰 Decorator


简介:

装饰器模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。比较官方,下面通过例子来解释一下

我的应用场景(也许不大合适),我写了一个坦克大战的小游戏,现在呢坦克能打出子弹,但是这个子弹比较单一不咋好看,如果我想在子弹上面加些装饰,那我是不是再加一个子弹类继承自游戏物体类,然后在这个新的子类当中画出新的子弹(比如给子弹加一个火花),那么如果以后有各种各样的千奇百怪的子弹出现,我就会有无数个子类,那么无疑是要爆炸了,如下图
image

那么是否有其他办法,当然是有的,如下图,我们定义一个普通子弹类(Bullet)。再定义一个装饰器GODecorator,其包含一个子弹对象,并可以对其进行“装饰”,这样一来我们每多加一种装饰,只需要多装饰一次即可,避免了重复设计大量的相似类。这就是装饰器模式的应用

image

在类图中,各个角色的说明如下:

GameObject,抽象构件

GameObject(游戏物体)是一个接口或者抽象类,是定义我们最核心的对象,也可以说是最原始的对象。

Bullet,具体构件,或者基础构件

Bullet(子弹)是最核心、最原始、最基本的接口或抽象类Component的实现,可以单独用,也可将其进行装饰。

GODecorator,抽象装饰器角色

一般是一个抽象类,继承自或实现GameObject,在它的属性里面有一个变量指向GameObject抽象构件。

TailDecorator、RectDecorator,具体装饰器角色

TailDecorator和RectDecorator是两个具体的装饰类,它们可以把基础构件装饰成新的东西,比如给子弹加个尾巴和方框。

解释比较抽象,我们看看代码实现:

GameObject

package com.mashibing.tank;
import java.awt.*;
/**
 * 游戏物体的父类,无论是坦克,子弹,爆炸等等都继承自这个类
 */
public abstract class GameObject {
    public int x, y;
 public abstract int getWidth();
 public abstract int getHeight();
 public abstract void paint(Graphics g);
}

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 Group group = Group.BAD;
 public Bullet(int x, int y, Dir dir, Group group) {
        this.x = x;
 this.y = y;
 this.dir = dir;
 this.group = group;
 rect.x = this.x;
 rect.y = this.y;
 rect.width = WIDTH;
 rect.height = HEIGHT;
 GameModel.getInstance().add(this);
 }
    @Override
 public void paint(Graphics g) {
        if(!living){
            GameModel.getInstance().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;
 }
    @Override
 public int getWidth() {
        return WIDTH;
 }
    @Override
 public int getHeight() {
        return HEIGHT;
 }
}

GODecorator

package com.mashibing.decorator;
import com.mashibing.tank.GameObject;
import java.awt.*;
public abstract class GODecorator extends GameObject {
    GameObject go;
 public GODecorator(GameObject go) {
        this.go = go;
 }
    @Override
 public abstract void paint(Graphics g);
}

TailDecorator

package com.mashibing.decorator;
import com.mashibing.tank.Bullet;
import com.mashibing.tank.GameObject;
import java.awt.*;
public class TailDecorator extends GODecorator {
    public TailDecorator(GameObject go) {
        super(go);
 }
    @Override
 public int getWidth() {
        return super.go.getWidth();
 }
    @Override
 public int getHeight() {
        return super.go.getHeight();
 }
    @Override
 public void paint(Graphics g) {
        this.x = go.x;
 this.y = go.y;
 go.paint(g);
 System.out.println("tail:"+(go instanceof Bullet));
 Color c = g.getColor();
 g.setColor(Color.WHITE);
 g.drawLine(go.x,go.y,go.x + getWidth(), go.y+getHeight());
 g.setColor(c);
 }
}

RectDecorator

package com.mashibing.decorator;
import com.mashibing.tank.Bullet;
import com.mashibing.tank.GameObject;
import java.awt.*;
public class RectDecorator extends GODecorator {
    public RectDecorator(GameObject go) {
        super(go);
 }
    @Override
 public int getWidth() {
        return super.go.getWidth();
 }
    @Override
 public int getHeight() {
        return super.go.getHeight();
 }
    @Override
 public void paint(Graphics g) {
        this.x = go.x;
 this.y = go.y;
 go.paint(g);
 System.out.println("rect:"+(go instanceof TailDecorator));
 Color c = g.getColor();
 g.setColor(Color.WHITE);
 g.drawRect(go.x,go.y,go.getWidth(),go.getHeight());
 g.setColor(c);
 }
}

使用

public class DecoratorDemo{
    public static void main(String[] args){
        GameObject bullet = new Bullet();
        // 第一次修饰,加个尾巴
        component = new TailDecorator(component);
        // 第二次修饰,加个方框
        component = new RectDecorator(component);
    }
}

总结:这就是装饰器的使用,那个如果我还要给子弹换个颜色,加个颜色装饰器即可,另外这些具体的装饰器我还可以用来装饰其他的物体,比如坦克也可以加个框或者加个尾巴,直接使用相同的装饰器即可,这样子就解决了继承带来的问题,比较容易扩展

标签:int,GameObject,模式,public,go,import,装饰,Decorator
来源: https://blog.csdn.net/qq_22717543/article/details/120389308

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有