From the design mode to see the glory of the King (xviii. Bridge mode)

See design mode (bridge mode) from the king of glory

I. Introduction

RGB glory of the King is a game player controls the hero of their choice to compete. Before the game started, players choose a hero want to operate, they would also pick Summoner skills appropriate for the hero. Summoner skills are universal, each player can freely mix and hero Summoner skills ₍₍◡ (╹◡╹) ◡₎₎

II. Mode motivation

Example: There are three heroes, each hero can be used with any of the four Summoner skills, there are two designs:
Design a way:

The first design analysis: Each hero comes with four kinds of Summoner skills, if you need to increase the hero, a hero for each additional class corresponding increase in four Summoner skills class, if the need to increase the skills you need to modify each category and a hero in adding new skills skills family

Design way:

The second design analysis: Clearly, for this variation there are two separate dimensions (i.e., for two reasons change) system, using the number of system design program two classes less, and more convenient system expansion. Design Option II is the bridge mode. Bridge mode conversion relation to the inheritance relationship, thereby reducing the coupling between the class and class, reducing the amount of code written

III. Bridge Mode

Bridge mode (Bridge Pattern): an abstraction and separated from its implementation, so that they can be independently varied. It is an object structural model, also known as the shank member (Handle and Body) mode or an interface (Interface) mode

桥接模式的使用场景:
在一下情况下可以使用桥接模式
■ 如果一个系统需要在构件的抽象化角色和具体角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系
■ 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合
■ 一个类存在两种独立变化的维度,且这两个维度都需要进行扩展
■ 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者
对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用

桥接模式涉及的设计原则有:
★ 封装变化
★ 多用组合,少用继承
★ 针对接口编程,不针对实现编程
★ 为交互对象之间的松耦合设计而努力
★ 类对于扩展开放,对修改关闭

桥接模式通用类图

桥接模式涉及的角色:
桥接模式包含如下角色:
Abstraction(抽象类)
用于定义抽象类的接口,它一般是抽象类而不是抽象接口,其中定义了一个Implementor(实现抽象类)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,它可以包含抽象的业务方法,还可以包含具体的业务方法
RefinedAbstraction(扩充抽象类)
扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中定义的抽象业务方法,在RefinedAbstract中可以调用在Implementor中定义的业务方法
Implementor(实现类接口)
定义实现类的接口,这个接口不一定要与Abstract的接口完全一致,事实上这两个接口可以完全不同,一般来讲,Implementor接口仅提供基本操作。而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了定义,而具体实现交给了其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用Implementor中定义的方法,使用关联关系来替代继承关系
ConcreteImplementor(具体实现类)
实现Implementor接口并且具体实现它,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给客户端具体的业务操作方法。

桥接模式优点:
⑴. 分离抽象接口及其实现部分,使得抽象和实现可以沿着各自的维度来变化
⑵. 桥接模式有时类似于多继承方案。但是多继承方案违背了类的单一职责原则,复用性比较差,而且多继承结构中累的个数非常庞大,桥接模式是比多继承方案更好的解决办法
⑶. 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原系统
⑷. 实现细节对客户透明,可以对用户隐藏实现细节
桥接模式缺点:
⑴. 桥接模式的引入会增加系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
⑵. 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性

我思故我在:桥接模式与策略模式之间的异同?
转载自:

四.结构图

五.设计类图

六.代码实现

创建抽象类(Hero类)

package com.practice.Hero;

import com.practice.Skill.Skill;
/*
 * 创建抽象类
 */
public abstract class Hero {
    Skill skill;
    
    public void setSkill(Skill _skill) {
        this.skill = _skill;
    }
    //定义使用技能的抽象方法
    public abstract void useSkill();
}

创建扩充抽象类(HouYi类)

package com.practice.Hero;
/*
 * 创建扩充抽象类
 */
public class HouYi extends Hero {
    public void useSkill() {
        String heroName = "后羿";
        this.skill.SummonerSkill(heroName);
    }
}

创建扩充抽象类(DaJi类)

package com.practice.Hero;
/*
 * 创建扩充抽象类
 */
public class DaJi extends Hero {
    public void useSkill() {
        String heroName = "妲己";
        this.skill.SummonerSkill(heroName);
    }
}

创建扩充抽象类(XiangYu类)

package com.practice.Hero;
/*
 * 创建扩充抽象类
 */
public class XiangYu extends Hero {
    public void useSkill() {
        String heroName = "项羽";
        this.skill.SummonerSkill(heroName);
    }
}

创建实现类接口(Skill类)

package com.practice.Skill;
/*
 * 创建实现类接口
 */
public interface Skill {
    public void SummonerSkill(String heroName);
}

创建具体实现类(JiPao类)

package com.practice.Skill;
/*
 * 创建具体实现类
 */
public class JiPao implements Skill {
    public void SummonerSkill(String heroName) {
        System.out.println("英雄["+heroName+"]携带召唤师技能——疾跑(100秒CD):增加30%移动速度持续10秒");
    }
}

创建具体实现类(KuangBao类)

package com.practice.Skill;
/*
 * 创建具体实现类
 */
public class KuangBao implements Skill {
    public void SummonerSkill(String heroName) {
        System.out.println("英雄[" + heroName + "]携带召唤师技能——狂暴(60秒CD):增加攻击速度60%,并增加物理攻击力10%持续5秒");
    }
}

创建具体实现类(ZhanSha类)

package com.practice.Skill;
/*
 * 创建具体实现类
 */
public class ZhanSha implements Skill {
    public void SummonerSkill(String heroName) {
        System.out.println("英雄[" + heroName + "]携带召唤师技能——斩杀(90秒CD):立即对身边敌军英雄造成其已损失生命值14%的真实伤害");
    }
}

XML配置文件config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <className>JiPao</className>
    <className>DaJi</className>
</config>

工具类读取XML文件(XMLUtilGame类)

package com.practice.Client;

import java.io.File;

import javax.xml.parsers.*;
import org.w3c.dom.*;


public class XMLUtilGame {
    //该方法用于从XML配置文件中提取具体类类名。并返回一个实例对象
    public static Object getBean(String args) {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src\\com\\practice\\Client\\config.xml"));
            
            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode = null;
            String cName = null;
            
            if(args.equals("skill")) {
                //获取包含类名的文本节点
                classNode = nl.item(0).getFirstChild();
                cName ="com.practice.Skill." + classNode.getNodeValue();
            }else if(args.equals("hero")) {
                //获取包含类名的文本节点
                classNode = nl.item(1).getFirstChild();
                cName = "com.practice.Hero." + classNode.getNodeValue();
            }
            //通过类名生成实例对象并将其返回
            Class<?> c = Class.forName(cName);
            @SuppressWarnings("deprecation")
            Object obj = c.newInstance();           
            return obj;
        }catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

创建客户端类(Client类)

package com.practice.Client;

import com.practice.Hero.Hero;
import com.practice.Skill.Skill;

public class Client {
    public static void main(String a[]) {
        Skill skill;
        Hero hero;
        
        skill = (Skill)XMLUtilGame.getBean("skill");
        hero = (Hero)XMLUtilGame.getBean("hero");
        
        hero.setSkill(skill);
        hero.useSkill();
    }
}

运行结果:

七.源代码下载

从王者荣耀看设计模式

Guess you like

Origin www.cnblogs.com/miaowulj/p/12163395.html