1. 程式人生 > >23中設計模式在遊戲伺服器裡面例子

23中設計模式在遊戲伺服器裡面例子

遊戲裡面有很多資料有用XML 形式配置,有用資料庫生成。

建立型(6)

   1.簡單工廠模式

由一個工廠物件決定創建出哪一種產品類的例項。

比如在遊戲活動設計的時候:每個活動配置資料的生成

public abstract class AbsLimitActivity{

    private byte id;
    private byte type;
    private String nam 

    private long startTime;
    private long endTime;

}

一個活動類的抽象類,當有新活動時繼承

在生成活動資料的時候外面可以用簡單工程更據活動ID 來生成放在manger裡面管理

public <T extends AbsActivity> T createActiviy(byte activityId){
		AbsActivity absActivity=null;
		switch (activityId) {
		case TIME_CAMPAIGN:absActivity=new LimitActTimeCampaign();break;
		case RICH_CAT: absActivity=new LimitActRichCat();break;
		case DAY_CHARGE: absActivity=new LimitActDayCharge();break;
		case CHARGE_REWARD:absActivity=new LimitActChargeReward();break;
		default:return null;
		}	
		return (T) absActivity;
	}

2、抽象工廠模式(Abstract Factory)

一個產品家族提供了統一的建立介面。當需要這個產品家族的某一系列的時候,可以從抽象工廠中選出相對系的系列來建立一個具體的工廠類別。

同樣活動裡面:

有2大類:一類是開服活動,另一類是配置活動開服,關服的時間

則可以有2個工廠來繼承

public abstract class AbsFactory {

	public abstract  <T extends AbsActivity> T createActiviy(int id);
	
}
public class OpenServerActivityFactory extends AbsFactory {

	@Override
	public <T extends AbsActivity> T createActiviy(int id) {
		// TODO Auto-generated method stub
		return null;
	}

}
public class ScheduleActivityFactory extends AbsFactory{

	@Override
	public <T extends AbsActivity> T createActiviy(int id) {
		// TODO Auto-generated method stub
		return null;
	}

}
public class ActiviytManager {

	public static final int OPEN_SERVRE_FACTORY = 1;
	public static final int SCHEDULE_FACTORY = 2;

	public AbsActivity createActivity(int factoryType, int activityId) {
		switch (factoryType) {
		case OPEN_SERVRE_FACTORY: new OpenServerActivityFactory().createActiviy(activityId);
			break;
		case SCHEDULE_FACTORY:new ScheduleActivityFactory().createActiviy(activityId);
			break;

		default:
			break;
		}
		return null;
	}
}

抽象工廠模式是在工廠方法上加了一個維度,抽象工廠模式簡單地說及時把工廠進行了一次包裝,工廠模式是把產品生產進行包裝,對外提供介面。既然抽象工廠模式是站在工廠方法肩膀上的,所以繼承工廠方法的所有優點。  抽象工廠對於工廠進行了包裝,使得使用和工廠(工廠和生產兩個級別的概念)的解耦,使得工廠類的擴充套件得到了實現,進一步增強了擴充套件性。

3、單例模式(Singleton)

一種常用的設計模式。在Java應用中,單例物件能保證在一個JVM中,該物件只有一個例項存在。

public class ActiviytManager {	
    /**
	 * 單例說明
	 */
	public static ActiviytManager instance;
	
	public static ActiviytManager getInstance() {
		if(instance==null) {
			synchronized(ActiviytManager.class){
				instance =new ActiviytManager();
			}
		}
		return instance;
	}
}

單例類只能有一個例項。  單例類必須自己建立自己的唯一例項。  單例類必須給所有其他物件提供這一例項。(靜態方法get例項) 

單例類比較靈活,畢竟從實現上只是一個普通的Java類,只要滿足單例的基本需求,你可以在裡面隨心所欲的實現一些其它功能,但是靜態類不行。

4、建造者模式(Builder)

建立單個類的模式,而建造者模式則是將各種產品集中起來進行管理,用來建立複合物件,所謂複合物件就是指某個類具有不同的屬性。

	/**
	 * 簡單例子 麼有新增屬性
	 * @param dataList
	 * @return
	 */
	public List<AbsActivity> buildActivityList(List<DbActivityData> dataList){
		List<AbsActivity> list=new ArrayList<>();
		for(DbActivityData data:dataList) {
			list.add(createActivity(data.getType(), data.getId()));
		}
		return list;
	}
	

在接著ActiviytManager  裡面再加上這個方法在這裡就可以說是用到建造者模式

建造者模式將很多功能整合到一個類裡,這個類可以創造出比較複雜的東西。所以與工程模式的區別就是:工廠模式關注的是建立單個產品,而建造者模式則關注建立符合物件,多個部分。因此,是選擇工廠模式還是建造者模式,依實際情況而定。

eg:遊戲例子,這裡取真實工程裡面的程式碼例項


/**
 * 道具建立(對歷史遺留做相容~~,簡單的整合)
 * @author ganzhuolin
 */
public class ItemBuild {
	
	private static Logger log = LoggerFactory.getLogger(ItemFactory.class);
	 
	/**
	 * 建立物品物件 帶有強化等級和卓越屬性的
	 * @param itemModelId			道具模型Id
	 * @param num					數量
	 * @param bind					是否繫結
	 * @param losttime				過期時間,秒數 (0 會讀配置的過期時間,其他值則直接賦值過期時間)
	 * @param grade				強化等級
	 * @param zhuoyue				卓越屬性
	 * @return {@link List<Item>}	道具集合
	 */
	public static List<Item> createItems(int itemModelId, int num, boolean bind, long losttime, int grade, String zhuoyue) {
		return createItems(itemModelId, num, bind, losttime, grade, 0, zhuoyue);
	}

	/**
	 * 建立物品物件 帶有強化等級
	 * @param itemModelId			道具id
	 * @param num					是否繫結
	 * @param bind					是否繫結
	 * @param losttime				過期時間,秒數 (0 會讀配置的過期時間,其他值則直接賦值過期時間)
	 * @param grade					等級
	 * @param unuse					沒有用到
	 * @return {@link List<Item>}	道具集合
	 */
	public static List<Item> createItems(int itemModelId, int num, boolean bind, long losttime, int grade, int unuse) {
		return createItems(itemModelId, num, bind, losttime, grade, 0, null);
	}

	/**
	 * 掉落物專用
	 * @param itemModelId			道具模型d
	 * @param num					是否繫結
	 * @param bind					是否繫結
	 * @param losttime				過期時間,秒數 (0 會讀配置的過期時間,其他值則直接賦值過期時間)
	 * @param grade					等級
	 * @param addAttribute			追加等級
	 * @return {@link List<Item>}	道具集合
	 */
	public static List<Item> createItemsForDropItem(int itemModelId, int num, boolean bind, long losttime, int grade, int addAttribute) {
		return createItems(itemModelId, num, bind, losttime, grade, addAttribute, null);
	}

	
	/**
	 * 建立普通物品(忽略了堆疊數限制)
	 * @param itemModelId
	 * @param num
	 * @return
	 */
	public static Item createCommonGoods(int itemModelId, int num) {
		Item item = new CommonGoods();
		item.setItemModelId(itemModelId);
		item.setNum(num);
		item.setId(IdFactroy.getId());
		return item;
	}

}

5、原型模式(Prototype)

通過給出一個原型物件來指明所有建立的物件的型別,然後用複製這個原型物件的辦法創建出更多同類型的物件

與工程模式沒有關係,從名字即可看出,該模式的思想就是將一個物件作為原型,對其進行復制、克隆,產生一個和原物件類似的新物件。

一個原型類,只需要實現Cloneable介面,覆寫clone方法,此處clone方法可以改成任意的名稱,因為Cloneable介面是個空介面,你可以任意定義實現類的方法名,如cloneA或者cloneB,因為此處的重點是super.clone()這句話,super.clone()呼叫的是Object的clone()方法。

在遊戲中有很多道具,裝備,消耗品,等等,他們都是有一些共同的資料,在上獨有的資料構成

public abstract class Item  implements Cloneable ,Serializable {
	/**
	 * 原型Id
	 */
	protected int itemModelId;

	/** 物品數量*/ 
	protected int num;
	/**
	 * 名字
	 */
	protected String name;
	
	abstract  Item   clone();
}

淺複製:將一個物件複製後,基本資料型別的變數都會重新建立,而引用型別,指向的還是原物件所指向的。

深複製:將一個物件複製後,不論是基本資料型別還有引用型別,都是重新建立的。簡單來說,就是深複製進行了完全徹底的複製,而淺複製不徹底。 

繼承上面抽象舉個例子:

​
public class Prototype extends Item {


	  /* 淺複製 */
	@Override
    public Object clone() throws CloneNotSupportedException {
    	Item proto = (Item) super.clone();
        return proto;
    }

    /* 深複製 */
    public Object deepClone() throws IOException, ClassNotFoundException {

        /* 寫入當前物件的二進位制流 */
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        /* 讀出二進位制流產生的新物件 */
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
	
}

​

///更新中 待續.......