1. 简单工厂模式
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式一般包含以下几个角色:
- 工厂角色(Factory):负责对象的创建,直接面向需要创建新产品对象的调用者,屏蔽产品具体的实现。
- 抽象产品角色(Product): 这里所说的抽象接口角色,其它就是工厂方法创建对象之后返回给调用者的接口或抽象类。是这一类产品的抽象描述定义。
- 具体产品角色(ConcreteProduct): 具体产品角色,这个就是创建的真实对象,是抽象产品角色的实现。
在游戏开发中,一般会有多个商店,对于客户端来,所有的商店都只有那几个共同的行为,所以可以抽象出来,做为抽象产品角色:
public interface IShop {
/**
* 检测购买的条件
* @param goodsId
* @return
*/
boolean checkBuyCondition(String goodsId);
/**
* 购买某个端口
* @param goodsId
*/
void buyGoods(String goodsId);
/**
* 获取商店所有的端口
* @return
*/
List<String> getGoods();
/**
* 此商店是否可以显示
* @return
*/
boolean isShow();
}
然后,具体的产品角色由子类实现,假如有三种不同类型的商店:ShopA,ShopB,ShopC。
那么创建商店的简单工厂就可以这样实现:
public class ShopSimpleFactory {
public IShop createShop(ShopEnum shopType) {
IShop shop = null;
switch (shopType) {
case SHOP_A:
shop = new ShopA();
break;
case SHOP_B:
shop = new ShopB();
break;
case SHOP_C:
shop = new ShopC();
break;
default:
break;
}
return shop;
}
}
2. 工厂方法模式
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
其实说白了,与简单工厂模式相比,它就是把工厂和产品一一对应起来,一个产品对应一个创建产品对象的工厂。
工厂方法模式包含如下角色:
- Product:抽象产品
- ConcreteProduct:具体产品
- Factory:抽象工厂
- ConcreteFactory:具体工厂
这个格式在框架封装上使用居多,比如日志框架,线程池,数据库连接池等。以线程池为例,它有个抽象工厂接口类:ThreadFactory,在创建线程池的时候,可以实现一个这样的工厂的子类,在创建线程池时做为参数传进去,当线程池需要创建线程的时候就可以直接调这个工厂的创建线程方法。一般在游戏服务器中,会有多种不同类型的线程池,可以使用此工厂模式给创建的线程命名不同的名字:
public class MyThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
return new Thread("业务线程");
}
}
创建线程池:
private ExecutorService executorService = Executors.newFixedThreadPool(3,new MyThreadFactory());
这样在获取当前线程的名字时,如果是使用的此线程池中的线程,就可以获取我们自定义的线程名字了。
3. 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
抽象工厂模式包含如下角色:
- AbstractFactory:抽象工厂
- ConcreteFactory:具体工厂
- AbstractProduct:抽象产品
- Product:具体产品
在抽象工厂模式中,一个工厂会创建多个产品,可以说当一堆产品都是一个工厂生产的时候,但是又有很多个不同的工厂时,可以考虑使用抽象工厂模式。
上面的定义不知道在说什么意思,想了半天,还是举个例子吧。比如电视,冰箱这类产品,电视和冰箱就是抽象产品,而加上品牌,比如海尔电视,海尔冰箱,格力电视,格力冰箱不是具体的产品,而海尔,格力就是具体的工厂。代码如下所示:
//抽象工厂
public interface IFactory {
//创建电脑
IComputer createComputer();
//创建电视
ITelevision createTelevision();
}
//海尔工厂
public class HaierFactory implements IFactory{
@Override
public IComputer createComputer() {
return new HaierComputer();
}
@Override
public ITelevision createTelevision() {
return new HaierTelevision();
}
}
//格力工厂
public class GeliFactory implements IFactory{
@Override
public IComputer createComputer() {
return new GeliComputer();
}
@Override
public ITelevision createTelevision() {
return new GeliTelevision();
}
}
//抽象产品
public interface IComputer {
}
public interface ITelevision {
}
//具体产品
public class GeliComputer implements IComputer{
}
public class GeliTelevision implements ITelevision{
}
public class HaierComputer implements IComputer{
}
public class HaierTelevision implements ITelevision{
}
在游戏开发中,也有类似的例子,比如副本模块(抽象工厂),A 副本,B 副本 (是具体工厂),每个副本有不同的支线(抽象产品),支线A,支线B,支线C (具体产品)等。
4. 建造者模式
造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。
建造者模式包含如下角色:
- Builder:抽象建造者
- ConcreteBuilder:具体建造者
- Director:指挥者(我觉得叫组装者更合适)
- Product:产品角色
所谓的抽象建造者,就是每个组装的步骤,所以不同的产品,组装的步骤和顺序是一样的,只是每个步骤赋的值不同罢了。
Director其实就是用来控制组装的步骤的,相当于一个装配车间,负责管理装配的流程。
代码示例可以更清楚的明白。
public class Product {//产品类,被组装的对象
private String partA;
private String partB;
public String getPartA() {
return partA;
}
public void setPartA(String partA) {
this.partA = partA;
}
public String getPartB() {
return partB;
}
public void setPartB(String partB) {
this.partB = partB;
}
}
public abstract class AbstractBuilder {//抽象建造者
protected Product product = new Product();
public abstract void buildA();
public abstract void buildB();
public Product getResult() {
return product;
}
}
public class ProductBuilder extends AbstractBuilder{//一个具体的建造者
@Override
public void buildA() {
product.setPartA("组装A部分");
}
@Override
public void buildB() {
product.setPartB("组装B部分");
}
}
public class ProductDirector { //装配者或指挥者
private AbstractBuilder builder;
public ProductDirector(AbstractBuilder builder) {
this.builder = builder;
}
public Product build() {
builder.buildB();
builder.buildA();
// 如果有n个步骤,依次添加即可。
return builder.getResult();
}
}
public static void main(String[] args) {//使用
AbstractBuilder builder = new ProductBuilder();
ProductDirector director = new ProductDirector(builder);
Product product = director.build();//把展示与创建者分离
System.out.println(product.getPartA());
}
5. 单例模式
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。不管在什么系统开发中,基本上都会用到这个模式。
单例模式的创建方式有以下几种:
-
懒汉模式 线程不安全,延迟初始化,
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
饿汉模式, 线程安全,比较常用
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
-
双重锁模式,线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
双重检查模式,进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。由于
singleton=new Singleton()
对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile
修饰signleton
实例变量有效,解决该问题 静态内部类单例模式
public class Singleton {
private Singleton(){
}
public static Singleton getInstance(){
return Inner.instance;
}
private static class Inner {
private static final Singleton instance = new Singleton();
}
}
只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,只有一个线程可以获得对象的初 始化锁,其他线程无法进行初始化,保证对象的唯一性。
-
枚举单例模式
默认枚举实例的创建是线程安全的,并且在任何情况下都是单例。实际上
- 枚举类隐藏了私有的构造器。
- 枚举类的域 是相应类型的一个实例对象
那么枚举类型日常用例是这样子的:
public enum Singleton {
INSTANCE
//doSomething 该实例支持的行为
//可以省略此方法,通过Singleton.INSTANCE进行操作
public static Singleton get Instance() {
return Singleton.INSTANCE;
}
}
具体使用哪种方式,可以根据自己的项目特点选择。但是记住一点,不要对单例序列化,这样的设计本身就是有问题的。