设计模式: 抽象工厂模式 - 概念、实现及netty中的抽象工厂模式

本文深入探讨了抽象工厂模式的概念与实现,通过轮胎和制动系统的实例讲解了其在创建一组相关对象的应用。进一步分析了Netty框架中抽象工厂模式的运用,特别是ByteBufAllocator在内存管理中的角色,展示了抽象工厂模式在实际项目中的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习设计模式不光要学习设计模式的思想,还要去深入理解,为什么要用这个设计模式。
如何深入理解?读优秀的框架代码,看别人代码,了解它们的使用场景。 - - - 博主老师(感谢他)

本文先介绍了抽象工厂模式的概念及简单实现。再介绍了netty中对抽象工厂模式的实现。最后总结了一点点思考。

概念

定义:为创建一组相关或相互依赖的对象提供一个接口,而不需要指定它们的具体实现类

怎么理解呢?例如所有的车有轮胎、制动系统等,但不同系列的车轮胎和制动系统又不一样。这里的轮胎、制动系统指的就是上面定义中所说的“一组相关的对象”。我们要提供的抽象工厂,将会帮我们创建这些产品。

实现

实现上面所说的轮胎、制动系统的例子

制动系统

public interface IBrake {
    void brake();
}
public class ABrake implements IBrake {
    @Override
    public void brake() {
        System.out.println("A级制动系统");
    }
}
public class BBrake implements IBrake {
    @Override
    public void brake() {
        System.out.println("B级制动系统");
    }
}

轮胎

public interface ITire {
    void tire();
}
public class ATire implements ITire {
    @Override
    public void tire() {
        System.out.println("A级轮胎");
    }
}
public class BTrie implements ITire {
    @Override
    public void tire() {
        System.out.println("B级轮胎");
    }
}

工厂

public interface Factory {

    ITire createTrie();

    IBrake createBrake();
}
public class AFactory implements Factory {
    @Override
    public ITire createTrie() {
        return new ATire();
    }

    @Override
    public IBrake createBrake() {
        return new ABrake();
    }
}
public class BFactory implements Factory {
    @Override
    public ITire createTrie() {
        return new BTrie();
    }

    @Override
    public IBrake createBrake() {
        return new BBrake();
    }
}

测试类

public static void main(String[] args) {
    Factory factory = new AFactory();
    factory.createBrake().brake();
    factory.createTrie().tire();

    Factory factory2 = new BFactory();
    factory2.createBrake().brake();
    factory2.createTrie().tire();
}

输出

A级制动系统
A级轮胎
B级制动系统
B级轮胎

其实非常简单,我们可以看到,A工厂创建出来的都是A系列产品,B工厂创建出来的都是B系列产品。

netty 中的抽象工厂模式

netty中ByteBufAllocator 是netty的内存管理器,负责分配所有的ByteBuf类型的内存。

类结构图(图片来自网络):
image

这里ByteBufAllocator就是我们的抽象工厂,PooledByteBBufAllocator和UnpooledByteBufAllocator就是具体的工厂。

这里比较有意思的是netty给 ByteBufAllocator抽象工厂设置了个默认工厂

public interface ByteBufAllocator {
    ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;
}

byteBufUtil根据allocType得到默认的工厂。

public final class ByteBufUtil {
    static final ByteBufAllocator DEFAULT_ALLOCATOR;

    static {
        String allocType = SystemPropertyUtil.get(
                "io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
        allocType = allocType.toLowerCase(Locale.US).trim();

        ByteBufAllocator alloc;
        if ("unpooled".equals(allocType)) {
            alloc = UnpooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: {}", allocType);
        } else if ("pooled".equals(allocType)) {
            alloc = PooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: {}", allocType);
        } else {
            alloc = PooledByteBufAllocator.DEFAULT;
            logger.debug("-Dio.netty.allocator.type: pooled (unknown: {})", allocType);
        }
    }

具体的工厂

public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
    @Override
    protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena<byte[]> heapArena = cache.heapArena;

        final ByteBuf buf;
        if (heapArena != null) {
            buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            buf = PlatformDependent.hasUnsafe() ?
                    new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
                    new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
        }

        return toLeakAwareBuffer(buf);
    }
    @Override
    protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena<ByteBuffer> directArena = cache.directArena;

        final ByteBuf buf;
        if (directArena != null) {
            buf = directArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            buf = PlatformDependent.hasUnsafe() ?
                    UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
                    new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
        }

        return toLeakAwareBuffer(buf);
    }
}
public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
    @Override
    protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
        return PlatformDependent.hasUnsafe() ?
                new InstrumentedUnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
                new InstrumentedUnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
    }
}
@Override
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
    final ByteBuf buf;
    if (PlatformDependent.hasUnsafe()) {
        buf = noCleaner ? new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) :
                new InstrumentedUnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
    } else {
        buf = new InstrumentedUnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
    }
    return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
}

节选了具体工厂的部分代码。有池的和无池的都需要提供 在堆和直接内存上分配ByteBuf的方法。但他们各自的实现确实不相同的。而客户端在调用的时候,只要调方法,不需要感知他们的实现。

思考

个人认为抽象工厂模式只要把握住:“一组相关的对象提供一个接口”这句话就行了。意思就是抽象A类需要abcd四个方法。子类A1和子类A2都有abcd方法,但是他们的实现可能不一样。
这个时候就可以用抽象工厂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值