设计模式简述(三)工厂模式

发布于:2025-04-06 ⋅ 阅读:(12) ⋅ 点赞:(0)

描述

工厂模式用以封装复杂的实例初始化过程,供外部统一调用

简单工厂(静态工厂)

如果对象创建逻辑简单且一致,可以使用简单工厂。传入想要生成的实例类型

public class HumanFactory {
    public static <T> T getInstance(Class<T> c) {
        try {
            return (T) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("生成对象异常", e);
        }
    }
}

工厂方法模式

多种类型产品初始化逻辑不一致时,可以采用不同工厂实例来初始化对应类型的产品
由于每种产品定义了对应的工厂类,因此工厂方法不需要类型参数就非常明确需要创建的实例

  • 声明工厂抽象定义
public abstract class AbstractProductFactory {
    public abstract Product createProduct();
}
  • 声明产品抽象定义
public interface Product {
    String getName();

    default void description() {
        System.out.println("产品名称:" + getName());
    }
}
  • 定义具体产品
public class Apple implements Product {
    @Override
    public String getName() {
        return "苹果";
    }
}

public class Banana implements Product {
    @Override
    public String getName() {
        return "香蕉";
    }
}

  • 定义产品对应的工厂
public class AppleFactory extends AbstractProductFactory {
    public Product createProduct() {
        // 苹果其他初始化逻辑
        return new Apple();
    }
}


public class BananaFactory extends AbstractProductFactory {
    public Product createProduct() {
        // 香蕉其他初始化逻辑
        return new Banana();
    }
}
  • 使用
public static void main(String[] args) {
    AbstractProductFactory appleFactory = new AppleFactory();
    Product product = appleFactory.createProduct();
    product.description();

    AbstractProductFactory bananaFactory = new BananaFactory();
    Product banana = bananaFactory.createProduct();
    banana.description();
}

抽象工厂

以上工厂方法,一个产品就需要一个工厂类。
如果产品本身就有一些共通的地方,我们可以将产品划分到同一个工厂的不同产品线,这些产品的生产可以共用一些资源。

比如,我的产品都分为大、中、小三种分类。分别进行不同的加工

  • 声明抽象水果
public interface Fruit {
    String getName();

    String getSize();

    default void description() {
        System.out.println("产品名称:" + getSize() + getName());
    }
}
  • 声明具体水果
public class BigApple implements Fruit {
    @Override
    public String getName() {
        return "苹果";
    }

    @Override
    public String getSize() {
        return "大号";
    }
}

public class MiddleApple implements Fruit {
    @Override
    public String getName() {
        return "苹果";
    }

    @Override
    public String getSize() {
        return "中号";
    }
}

public class SmallApple implements Fruit {
    @Override
    public String getName() {
        return "苹果";
    }

    @Override
    public String getSize() {
        return "小号";
    }
}
public class BigBanana implements Fruit {
    @Override
    public String getName() {
        return "香蕉";
    }

    @Override
    public String getSize() {
        return "大号";
    }
}

public class MiddleBanana implements Fruit {
    @Override
    public String getName() {
        return "香蕉";
    }

    @Override
    public String getSize() {
        return "中号";
    }
}

public class SmallBanana implements Fruit {
    @Override
    public String getName() {
        return "香蕉";
    }

    @Override
    public String getSize() {
        return "小号";
    }
}
  • 声明抽象工厂
public abstract class AbstractFruitFactory {
    abstract Fruit bigFruit();
    abstract Fruit middleFruit();
    abstract Fruit smallFruit();
}
  • 定义具体工厂
public class AppleFruitFactory extends AbstractFruitFactory{
    @Override
    Fruit bigFruit() {
        return new BigApple();
    }

    @Override
    Fruit middleFruit() {
        return new MiddleApple();
    }

    @Override
    Fruit smallFruit() {
        return new SmallApple();
    }
}
public class BananaFruitFactory extends AbstractFruitFactory {
    @Override
    Fruit bigFruit() {
        return new BigBanana();
    }

    @Override
    Fruit middleFruit() {
        return new MiddleBanana();
    }

    @Override
    Fruit smallFruit() {
        return new SmallBanana();
    }
}

增加工厂管理类

当抽象工厂的子类扩展时,调用方需要和各个子类工厂交互,在一定程度上违反了迪米特法则。
我们可以将工厂子类交由工厂管理类进行管理,调用方只需要和这个管理类交互即可

public final class FruitFactoryManager {
    private static Map<String, AbstractFruitFactory> register = new HashMap<>();
    
    static {
        register.put("apple", new AppleFruitFactory());
        register.put("banana", new BananaFruitFactory());
    }
    
    public static AbstractFruitFactory getFactory(String factoryCode) {
        return register.get(factoryCode);
    }
}

使用

public class Sample {
    public static void main(String[] args) {
        AbstractFruitFactory appleFactory = new AppleFruitFactory();
        Fruit smallApple = appleFactory.smallFruit();
        smallApple.description();
        Fruit middleApple = appleFactory.middleFruit();
        middleApple.description();
        Fruit bigApple = appleFactory.bigFruit();
        bigApple.description();


        AbstractFruitFactory bananaFactory = new BananaFruitFactory();
        Fruit smallBanana = bananaFactory.smallFruit();
        smallBanana.description();
        Fruit middleBanana = bananaFactory.middleFruit();
        middleBanana.description();
        Fruit bigBanana = bananaFactory.bigFruit();
        bigBanana.description();
    }
}