写给自己看的设计模式之《工厂模式》

一. 简单工厂模式

又称为静态工厂方法(Static Factory Method)模式,它属于创建型模式,专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

1.1 场景

  • 工厂类负责创建的对象比较少,不会造成业务逻辑太复杂
  • 客户端只知道传入工厂类的参数,对如何创建类并不关心

1.2 优点

  • 实现了对责任的分割,工厂类负责创建产品对象,客户端负责“消费”即可,且不需要记住产品类的类名

1.3 缺点

  • 工厂类负责所有产品的创建,一旦不能工作将影响整个系统
  • 违反开闭原则,一旦需要添加产品就需要修改工厂类的实现逻辑,产品太多可能造成工厂类逻辑复杂
  • 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
1. 创建teacher接口
/**
 * teacher接口,定义方法
 *
 * @author dkangle
 */
public interface Teacher {
    
    
    void teach();
}

2. 实现teacher接口
/**
 * 数学老师
 *
 * @author dkangel
 */
public class MathTeacher implements Teacher {
    
    
    @Override
    public void teach() {
    
    
        System.out.println("I teach math.");
    }
}

/**
 * 英语老师
 *
 * @author dkangel
 */
public class EnglishTeacher implements Teacher {
    
    
    @Override
    public void teach() {
    
    
        System.out.println("I teach english.");
    }
}

3. 创建teacher工厂类,并创建静态方法获取teacher实例
/**
 * teacher工厂类
 * <p>
 * 定义一个工厂类专门实例化teacher实例,这些实例具有相同的父类
 *
 * @author dkangel
 */
public static class TeacherFactory {
    
    
    public Teacher getTeacher(String type) {
    
    
        if ("math".equals(type)) {
    
    
            return new MathTeacher();
        } else if ("english".equals(type)) {
    
    
            return new EnglishTeacher();
        }
        return null;
    }
}

4. 使用
/**
 * 简单工厂使用类
 *
 * @author dkangel
 */
public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 数学老师
        Teacher teacher = TeacherFactory.getTeacher("math");
        teacher.teach();

        // 英语老师
        teacher = TeacherFactory.getTeacher("english");
        teacher.teach();
    }
}

二. 工厂方法模式

又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。

2.1 场景

  • 当一个类不知道它所需要的对象的类时
  • 当一个类希望通过其子类来指定创建对象时

2.2 优点

  • 符合开闭原则,新增产品时,只需要增加具体的产品类和工厂子类即可
  • 符合单一职责原则,一个工厂子类只负责创建对应的产品
  • 不使用静态工厂方法,可以形成基于继承的等级结构

2.3 缺点

  • 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度
  • 一个具体工厂只能创建一种具体产品
1. 创建抽象工厂类
/**
 * teacher接口
 *
 * @author dkangel
 */
public interface Teacher {
    
    
    /**
     * 教学
     */
    void teach();
}

2. 创建抽象teacher类
/**
 * teacher类
 *
 * @author dkangel
 */
public abstract class Teacher {
    
    
    /**
     * 教学
     */
    public abstract void teach();
}

3. 创建具体的teacher类
/**
 * math teacher类
 *
 * @author dkangel
 */
public class MathTeacher implements Teacher {
    
    
    @Override
    public void teach() {
    
    
        System.out.println("I am math teacher.");
    }
}

4. 创建具体工厂类
/**
 * 具体工厂类 math teacher factory
 * 
 * @author dkangel
 */
public class MathFactory extends Factory {
    
    
    @Override
    public Teacher getTeacher() {
    
    
        return new MathTeacher();
    }
}

5. 使用
/**
 * 工厂方法使用类
 *
 * @author dkangel
 */
public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 数学老师
        AbstractFactory factory = new MathFactory();
        Teacher teacher = factory.getTeacher();

        // 英语老师
        factory = new EnglishFactory();
        teacher = factory.getTeacher();
    }
}

三. 抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。围绕超级工厂创建其他工厂

3.1 场景

  • 一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提
  • 这个系统有多个系列产品,而系统中只消费其中某一系列产品
  • 系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现

3.2 优点

  • 降低耦合
    抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
  • 更符合开-闭原则
    新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
  • 符合单一职责原则
    每个具体工厂类只负责创建对应的产品
  • 不使用静态工厂方法,可以形成基于继承的等级结构。

3.3 缺点

  • 抽象工厂模式很难支持新种类产品的变化。
    这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则
1. 创建电脑接口
/**
 * 电脑接口
 *
 * @author dkangel
 */
public interface Computer {
    
    
    /**
     * 写代码
     */
    void code();
}

2. 创建电脑实现类
public class HuaweiComputer implements Computer {
    
    
    @Override
    public void code() {
    
    
        System.out.println("Huawei Computer code.");
    }
}
public class AppleComputer implements Computer {
    
    
    @Override
    public void code() {
    
    
        System.out.println("Apple Computer code.");
    }
}

3. 创建手机接口
/**
 * 手机接口
 *
 * @author dkangel
 */
public interface Phone {
    
    
    /**
     * 打电话
     */
    void call();
}

4. 创建手机实现类
public class HuaweiPhone implements Phone {
    
    
    @Override
    public void call() {
    
    
        System.out.println("Huawei Phone call.");
    }
}
public class ApplePhone implements Phone {
    
    
    @Override
    public void call() {
    
    
        System.out.println("Apple Phone call.");
    }
}

5. 创建抽象工厂类
/**
 * 工厂类
 *
 * @author dkangel
 */
public abstract class AbstractFactory {
    
    
    /**
     * 生产手机
     *
     * @return Phone
     */
    public abstract Phone manufacturePhone(String company);

    /**
     * 生产电脑
     *
     * @return Computer
     */
    public abstract Computer manufactureComputer(String company);
}

6. 创建电脑、手机工厂类
/**
 * Computer工厂类
 *
 * @author dkangel
 */
public class ComputerFactory extends AbstractFactory {
    
    
    @Override
    public Phone manufacturePhone(String company) {
    
    
        return null;
    }

    @Override
    public Computer manufactureComputer(String company) {
    
    
        if ("Huawei".equalsIgnoreCase(company)) {
    
    
            return new HuaweiComputer();
        } else if ("Apple".equalsIgnoreCase(company)) {
    
    
            return new AppleComputer();
        }
        return null;
    }
}
/**
 * Phone工厂类
 *
 * @author dkangel
 */
public class PhoneFactory extends AbstractFactory {
    
    
    @Override
    public Phone manufacturePhone(String company) {
    
    
        if ("Huawei".equalsIgnoreCase(company)) {
    
    
            return new HuaweiPhone();
        } else if ("Apple".equalsIgnoreCase(company)) {
    
    
            return new ApplePhone();
        }
        return null;
    }

    @Override
    public Computer manufactureComputer(String company) {
    
    
        return null;
    }
}

7. 创建超级工厂类
/**
 * 超级工厂类,用于创建其具体的工厂类
 *
 * @author dkangel
 */
public class FactoryProducer {
    
    
    /**
     * 根据type获取具体的工厂
     *
     * @param type 工厂类型
     * @return AbstractFactory
     */
    public static AbstractFactory getFactory(String type) {
    
    
        if ("Phone".equalsIgnoreCase(type)) {
    
    
            return new PhoneFactory();
        } else if ("Computer".equalsIgnoreCase(type)) {
    
    
            return new ComputerFactory();
        }
        return null;
    }
}

8. 使用
/**
 * 抽象工厂使用类
 *
 * @author dkangel
 */
public class Main {
    
    
    public static void main(String[] args) {
    
    
        // 获取Phone工厂
        AbstractFactory phoneFactory = FactoryProducer.getFactory("phone");
        // 获取Huawei手机
        Phone phone = phoneFactory.manufacturePhone("Huawei");
        phone.call();
        // 获取Apple手机
        phone = phoneFactory.manufacturePhone("Apple");
        phone.call();

        AbstractFactory computerFactory = FactoryProducer.getFactory("computer");
        // 获取Huawei电脑
        Computer computer = computerFactory.manufactureComputer("Huawei");
        computer.code();
        // 获取Apple电脑
        computer = computerFactory.manufactureComputer("Apple");
        computer.code();
    }
}

猜你喜欢

转载自blog.csdn.net/Dkangel/article/details/105723774