工厂模式学习笔记(简单工厂模式、工厂方法模式、抽象工厂模式)

是什么?

工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化的类。工厂模式遵循开闭原则,即对扩展开放,对修改关闭。

在Java中,工厂模式通常有三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。

  1. 简单工厂模式:在简单工厂模式中,一个工厂类负责创建多个不同类型的对象。这种模式的开闭原则体现在新增一种产品类型时,只需要修改工厂类即可,而不需要修改客户端代码。

  2. 工厂方法模式:工厂方法模式通过定义一个创建对象的接口,但将实际创建工作推迟到子类中。这样,每个子类都可以根据需要创建适合自己需求的对象。这符合开闭原则,因为新增的产品类型只需要添加对应的工厂子类,而不需要修改已有的代码。

  3. 抽象工厂模式:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式允许系统在不修改具体工厂的情况下引入新的产品,符合开闭原则的要求。

总的来说,工厂模式通过将对象的创建和使用分离,使得系统更容易扩展新的产品类型,而不需要修改已有的代码,从而符合开闭原则的设计原则。


关于开闭原则的补充:
对于扩展开放(Open for Extension):工厂模式允许系统在不修改已有代码的情况下引入新的产品类型。当需要添加新的产品类型时,只需要创建新的具体产品类和对应的工厂类,而不需要修改已有的代码。这种灵活性使得系统能够轻松地适应变化和扩展,符合开放的特性。

对于修改关闭(Closed for Modification):工厂模式通过将对象的创建和使用分离,使得客户端代码不依*赖于具体产品类,而是依赖于抽象产品类和工厂类。这意味着当需要修改已有的产品类型或工厂类时,不需要*修改客户端代码,只需要修改对应的具体工厂类或具体产品类即可。这种设计原则使得系统的稳定性得到保
障,符合关闭的特性。

简单工厂模式

新建一个“鼠标接口”,声明一个方法

package demo.pattern.factory.entity;

public interface Mouse {
    void sayHi();
}

再新建两个鼠标类,实现接口,他们分别是戴尔鼠标和惠普鼠标

package demo.pattern.factory.entity;

public class DellMouse implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是戴尔鼠标");
    }
}


package demo.pattern.factory.entity;

import demo.annotation.TestAnnotation;

public class HpMouse  implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}

这时我们就可以创建一个鼠标工厂



public class MouseFactory {
    public static Mouse  createMouse(int type){
        switch (type) {
            case 0: return new DellMouse();
            case 1: return new HpMouse();
            default: return new DellMouse();
        }
    }

    public static void main(String[] args) {
        Mouse mouse = MouseFactory.createMouse(1);
        mouse.sayHi();
    }
}

​

以上是简单工厂模式的实例,简单工厂隐藏了对象创建的细节,客户端不需要自己创建实例,只需要告知需要什么品牌的鼠标。

简单工厂模式的适用场景:

        1、需要创建的对象少;

        2、客户端不关心对象的创建过程;

简单工厂模式的优缺点:

        优点:可以对创建的对象进行“加工”,对客户端隐藏相关细节

        缺点:1、因创建逻辑复杂或出啊关键对象过多而造成代码臃肿;

                   2、新增、删除子类均会违反开闭原则

例如,对现有的工厂,添加一个新的产品类,“联想鼠标”

package demo.pattern.factory.entity;

public class LenovoMouse implements Mouse {
    @Override
    public void sayHi() {
        System.out.println("我是联想鼠标");
    }
}

它扩展了“鼠标接口”,并未对接口和其他产品类产生修改,但是对于工厂类

​

public class MouseFactory {
    public static Mouse  createMouse(int type){
        switch (type) {
            case 0: return new DellMouse();
            case 1: return new HpMouse();
            case 2: return new LenovoMouse();
            default: return new DellMouse();
        }
    }

    public static void main(String[] args) {
        Mouse mouse = MouseFactory.createMouse(1);
        mouse.sayHi();
    }
}

​

需要新添加一钟情况,修改了原有代码,违反了开闭原则

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类

对类的实例化延迟到其子类

创建一个“鼠标工厂接口”,声明一个方法“生产鼠标”

package demo.pattern.factory.method;

import demo.pattern.factory.entity.Mouse;

public interface MouseFactory {
    Mouse createMouse();
}

接下来,新建三个实体类实现“鼠标工厂接口”:

package demo.pattern.factory.method;

public class DellMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }
}

package demo.pattern.factory.method;

public class HpMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse() {
        return new HpMouse();
    }
}

package demo.pattern.factory.method;


public class LenovoMouseFactory  implements MouseFactory{
    @Override
    public Mouse createMouse() {
        return new LenovoMouse();
    }
}

此时新增产品类,只需新对应工厂类,工厂方法模式不会违反开闭原则,同时也隐藏了创建具体实例,且具有单一职责。

工厂方法模式,是简单工厂模式的进一步抽象和扩展,保留了简单工厂的封装优点,让扩展变得简单,让继承可行,增加了多态的体现。

但是随着新产品类的不断增加,对应工厂类也随之增加,系统类的个数成倍增加,增加了系统的复杂度,还需要创造同等数量的controller类,使代码变得臃肿。添加子类时“拖家带口”

抽象工厂模式

        抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口;

        抽象工厂模式侧重的是同一产品族,工厂方法模式更侧重同一产品等级

假设,产品“鼠标”“键盘”需要成套购买。

创建“键盘接口”

package demo.pattern.factory.entity;

public interface Keyboard {
    void sayHello();
}

 创建实体类,实现就“键盘接口”

package demo.pattern.factory.entity;

public class DellKeyboard implements Keyboard {
    @Override
    public void sayHello() {
        System.out.println("我是戴尔键盘");
    }
}

package demo.pattern.factory.entity;

public class HpKeyboard implements Keyboard {
    @Override
    public void sayHello() {
        System.out.println("我是惠普键盘");
    }
}

package demo.pattern.factory.entity;

public class LenovoKeyboard implements Keyboard {
    @Override
    public void sayHello() {
        System.out.println("我是联想键盘");
    }
}

创建“电脑工厂接口”,声明生产“鼠标”“键盘”的方法

package demo.pattern.factory.abstractf;

import demo.pattern.factory.entity.Keyboard;
import demo.pattern.factory.entity.Mouse;

public interface ComputerFactory {
    Mouse createMouse();
    Keyboard createKeyboard();
}

创建戴尔,惠普,联想的对应工厂类,实现电脑工厂接口

package demo.pattern.factory.abstractf;

public class DellComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new DellMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new DellKeyboard();
    }
}


package demo.pattern.factory.abstractf;


public class HpComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new HpMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new HpKeyboard();
    }
}

package demo.pattern.factory.abstractf;


public class LenovoComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse() {
        return new LenovoMouse();
    }

    @Override
    public Keyboard createKeyboard() {
        return new LenovoKeyboard();
    }
}

之后我们就可以来生产对应对应品牌的“键鼠套装”

package demo.pattern.factory.abstractf;


public class AbstractFactoryDemo {
    public static void main(String[] args) {
        ComputerFactory cf = new HpComputerFactory();
        Mouse mouse = cf.createMouse();
        Keyboard keyboard = cf.createKeyboard();
        mouse.sayHi();
        keyboard.sayHello();
    }
}

抽象工厂模式可以生产多个等级的产品,解决了工厂模式只支持一种产品的弊端。

新增一个产品族时,只需新增加一个新的具体工厂,不需要修改代码。

但是,增加新产品时,依旧违反开闭原则,增加系统复杂度。

spring解决这个问题,依靠的是工厂模式和反射机制结合的I Spring IOC容器来实现Bean的创建。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值