方案1:
背景:
游戏服务器中,多态可以说体现的淋漓尽致。
如:
1.开启条件。有的系统是根据玩家等级,有的是根据通关第几关。
2.商店可能有不同类型的商店。
3.任务系统中,不同的计数类型,不同的任务目标类型。
4.功能开启中,不同的系统开启条件不同。
....
稍微复杂一点的系统都会涉及到多态。
我们往往需要采用一种一致的接口去处理,这样子可以避免冗余代码。但是他们需要的数据却不同。
经过我的实践,我觉得一种比较好的写法如下:
ETest.java // 枚举所有的类型
- package org.example.enumDuoTai;
-
- import org.example.enumDuoTai.data.ATestData;
- import org.example.enumDuoTai.data.BTestData;
- import org.example.enumDuoTai.data.ITestData;
-
- public enum ETest {
- A {
- @Override
- public void test(ITestData data) {
- ATestData aTestData = data.get();
-
- System.out.println("roleId="+ aTestData.getRoleId() + " a=" + aTestData.getA());
- }
- },
-
-
- B {
- @Override
- public void test(ITestData data) {
- BTestData bTestData = data.get();
-
- System.out.println("sn="+ bTestData.getSn() + " B=" + bTestData.getB());
- }
- },
- ;
-
- public abstract void test(ITestData data);
- }
ITestData.java // 数据接口
- package org.example.enumDuoTai.data;
-
- @SuppressWarnings("all")
- public interface ITestData {
- default
T get(){ - return (T)this;
- }
- }
ATestData.java // 数据参数实现1
- package org.example.enumDuoTai.data;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
-
- @Data
- @AllArgsConstructor
- public class ATestData implements ITestData{
- private long roleId;
- private int a;
- }
BTestData.java // 数据参数实现
- package org.example.enumDuoTai.data;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
-
- @Data
- @AllArgsConstructor
- public class BTestData implements ITestData{
- private int sn;
- private String b;
- }
Main.java
- package org.example.enumDuoTai;
-
- import org.example.enumDuoTai.data.ATestData;
- import org.example.enumDuoTai.data.BTestData;
-
- public class Main {
- public static void main(String[] args) {
- ETest.A.test(new ATestData(4097, 1));
-
- ETest.B.test(new BTestData(1001, "jn"));
- }
- }
-
- /*
- roleId=4097 a=1
- sn=1001 B=jn
- */
总结:
这样子,我们就可以在枚举中无限扩展,像我做的MMO游戏,排行榜来说,最多也就35种,看起来行数多了点,但是实际上维护性还是可以。这种枚举的多态,实现比较简单。
这样子通过接口,让所有的操作都是强类型的,是比较简单的。
而且枚举有values,天然实现了遍历,也就是工厂模式。
--------------
方案2:
背景:
我现在要设计一个复杂的属性系统,输入参数是多变的,导致我很难搞,大部分来源都是:PlayerEntity,但是有的来源可能是:国王等,导致输入参数差异是很大的,之前做的卡牌游戏,都是: 只有一个Role上下文就可以了。
后面在mt项目中,发现了IxxxData(get方法)+多种实现进行实现。
现在看到了通过泛型+子类 来构造上下文。
ITest.java
- package org.example.testGeneric;
-
- public interface ITest<T> {
- int test(T t);
- }
TestAddImpl.java
- package org.example.testGeneric;
-
- public class TestAddImpl implements ITest
{ - private int a;
-
- private int b;
-
- public TestAddImpl(int a, int b) {
- this.a = a;
- this.b = b;
- }
-
- @Override
- public int test(TestAddImpl testA) {
- return a + b;
- }
- }
TestSubImpl.java
- package org.example.testGeneric;
-
- public class TestSubImpl implements ITest
{ - private String str;
- private int age;
-
- public TestSubImpl(String str, int age) {
- this.str = str;
- this.age = age;
- }
-
- @Override
- public int test(TestSubImpl testSub) {
- return (str == null || str.isEmpty()) ? 0 : str.length() + age;
- }
- }
Main.java
- package org.example.testGeneric;
-
- public class Main {
- public static void main(String[] args) {
- test(new TestAddImpl(1, 2));
- test(new TestSubImpl("jn", 18));
- }
-
- public static void test(ITest iTest) {
- System.out.println(iTest.test(iTest));
- }
- }