工厂模式

工厂模式

用工厂方法代替new操作

什么情况下适合工厂模式
1.有一组相似的对象需要创建(比如说:创建毛巾的工厂不能用来创建汽车)
2.在编码时不能预计需要创建那种类的实例(比如说,创建水果,但是需要创建的水果有很多,暂时不知道需要创建多少水果)
项目中的现状:
在软件系统中经常面临着,对象的创建工作,由于需求的变化,这个对象可能随之也会发生变化,但它却拥有比较稳定的接口。
为此,我们需要提供一种封装机制来隔离出这个易变对象的变化,从而保证系统中其他依赖该对象的对象不随着需求变化而变化。
在这里插入图片描述

简单入门:
先定义一个接口


/**
 * 发型接口
 */
public interface HairInterface {
    //实现发型
    public void draw();
}

在实现两个类:


/**
 * 左偏分发型
 */
public class LeftHair implements HairInterface {
    @Override
    public void draw() {
        System.out.println("左偏分发型");
    }
}

package factory_mode;

public class RightHair implements HairInterface {
    @Override
    public void draw() {
        System.out.println("这是右偏分发型");
    }
}

在创建一个产品类;

package factory_mode;

/**
 * 发型工厂
 */
public class HairFactory {
    /**
     * 根据类型来创建对象
     */
    public HairInterface getHair(String key){
        if("left".equals(key)){
            return new LeftHair();
        } else if ("right".equals(key)) {
            return new RightHair();
        }
        return null;
    }
}

调用:

package factory_mode;

public class FactoryTest {
    public static void main(String[] args) {
       /* HairInterface left = new LeftHair();
        left.draw();*/
        HairFactory hairFactory = new HairFactory();
        HairInterface left = hairFactory.getHair("left");
        if(left != null) {
            left.draw();
        }
    }
}

这个时候,工厂模式的优点就出现了,首先,客户端不需要创建对象了,直接给一个left就可以创建出一个对象,也不需要记忆很多类名。产品的实现和客户端进行了分离。
但是,现在有一个缺点,当我需要增加其他的类的时候,需要在else if 里面进行加
在这里插入图片描述
增加一个加一行,很麻烦。而且这里要进行判断,效率也慢,于是我们就通过类名,通过反射来创建对象。

    /**
     * 利用类名来生产对象
     */
    public HairInterface getHairByClass(String className){
        try {
            HairInterface hair = (HairInterface)Class.forName(className).newInstance();
            return hair;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

代码如下:
测试如下:

package factory_mode;

public class FactoryTest {
    public static void main(String[] args) {
       /* HairInterface left = new LeftHair();
        left.draw();*/
        HairFactory hairFactory = new HairFactory();
       /* HairInterface left = hairFactory.getHair("left");
        if(left != null) {
            left.draw();
        }*/
       hairFactory.getHairByClass("factory_mode.LeftHair").draw();
    }
}

可以达到预期效果。这样在增加一个发型,我们不需要用else if 了。自己通过类名创建。
但是,这个类名是全类名,感觉还是挺麻烦的,这里我在对其进行升级。

 /**
     * 利用类名来生产对象
     */
    public <T extends HairInterface> HairInterface getHairByClass(Class<T> c){
        try {
            HairInterface hair = (HairInterface)Class.forName(c.getName()).newInstance();
            return hair;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

升级如下:现在只需要传入class文件即可。而且引进了泛型,传入的类必须是集成HairInterface接口。对输入的类进行了一个限制。
此时,客户端的代码就如下:

package factory_mode;

public class FactoryTest {
    public static void main(String[] args) {
       /* HairInterface left = new LeftHair();
        left.draw();*/
        HairFactory hairFactory = new HairFactory();
       /* HairInterface left = hairFactory.getHair("left");
        if(left != null) {
            left.draw();
        }*/
       hairFactory.getHairByClass(RightHair.class).draw();
    }
}

这时候,我新建了一个类的时;

package factory_mode;

public class InHair implements HairInterface {
    @Override
    public void draw() {
        System.out.println("这是中分发型");
    }
}

客户端也可以直接进行测试,无须通过修改工厂类以及其他
在这里插入图片描述
如上:已经可以实现了一个发型工厂实现类,这个类可以产生各种发型。
但是 要是有系列的话就不一样了。比如说圣诞系列的头发,而且每个系列都是有男孩女孩,当然,以上代码也可以实现,但是效果就非常不好,而且会显得很臃肿。
这时候,就需要抽象工厂模式了。

抽象工厂模式定义

为创建一组相关或者相互依赖的对象提供一个接口,无需指定它们的具体类。
由于我们的需求是,需要有男孩女孩,有需要不同有不同的系列,所以,用普通工厂模式就不行了。
首先我需要创建男孩和女孩就需要一个工厂,这个工厂设置为接口,不是像刚才一样的类

package factory_mode;

/**
 * 人物的实现接口
 */
public interface PersonFactory {
    //男孩接口
    public Boy getBoy();

    // 女孩接口
    public Girl getGirl();
}

然后男孩和女孩也是接口

package factory_mode;

/**
 * 男孩
 *
 */
public interface Boy {
    public void drawMan();
}

package factory_mode;

/**
 * 女孩
 */
public interface Girl {
    public void drawWomen();
}

每个男孩有很多系列,假设有新年系列和圣诞系列

package factory_mode;

/**
 * 新年系列的男孩子
 */
public class HNBoy implements Boy {
    @Override
    public void drawMan() {
        System.out.println("新年系列的男孩子");
    }
}

package factory_mode;

public class MCBoy implements Boy {
    @Override
    public void drawMan() {
        System.out.println("圣诞系列的男孩子");
    }
}

女孩也是有新年系列和圣诞系列

package factory_mode;

/**
 * 圣诞系列的女孩
 */
public class MCGirl implements Girl {
    @Override
    public void drawWomen() {
        System.out.println("圣诞系列的女孩");
    }
}

package factory_mode;

public class HNGirl implements Girl {
    @Override
    public void drawWomen() {
        System.out.println("圣诞系列的女孩");
    }
}

这时候,就可以用圣诞系列的工厂来创建圣诞系列的男孩或者女孩了

package factory_mode;

/**
 * 圣诞系列加工厂
 */
public class MCFctory implements PersonFactory {
    @Override
    public Boy getBoy() {
        return new MCBoy();
    }

    @Override
    public Girl getGirl() {
        return new MCGirl();
    }
}

这样当客户端需要圣诞男孩时,只需要调用MCFtory的getBoy()方法就好了。
上面这个案例的因素数有两个 第一个性别 第二个因素为系列 ,不管有多少性别和多少系列。都只有两个因素而已。对于有两个因素的,就应该使用抽象工厂模式。把工厂用接口实现。

下面在来举一个例子:
假设我要生产产品,假设产品有等级、和种类两个因素。假设我需要生成两个等级,三个种类的产品。
首先我先写一个产品抽象类;

package factory_mode.product;

/**
 * 抽象产品类
 */
public abstract class AbstractProduct {
    public void shareMethod(){
        System.out.println("这是产品类的公共方法");
    }
    //每个产品相同方法,不同实现
    public abstract void doSomething();
}

然后,再写上三个具体的产品实现类ABC;

package factory_mode.product;

public class ProductA extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是产品A");
    }
}


public class ProductB extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是产品B");
    }
}

public class ProductC extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是产品C");
    }
}

在创建三款普通级产品

public class SubProductA extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是普通款产品A");
    }
}

public class SubProductB extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是普通款产品B");
    }
}

public class SubProductC extends AbstractProduct {
    @Override
    public void doSomething() {
        System.out.println("我是普通款产品C");
    }
}

这样六款产品就好了,其中有两个因素,产品的等级和产品的种类;
重点来了:下面需要创建一个抽象工厂,有几个产品等级就需要有几个创建方法
这里其实是解决了一个因素 就是解决产品种类的这个因素;

package factory_mode.product;

/**
 * 抽象工厂
 * 有几个产品等级,就需要有几个创建方法
 */
public interface AbstracCreator {
    //创建A产品
    public AbstractProduct createProductA();
    //创建B产品
    public AbstractProduct createProductB();
    //创建C产品
    public AbstractProduct createProductC();
}

然后,在创建三个具体的实现类
这里其实是解决了产品等级的这个因素:

package factory_mode.product;

/**
 * 实现了抽象工厂
 * 只创建高级别的产品
 */
public class Creator implements AbstracCreator {
    @Override
    public AbstractProduct createProductA() {
        System.out.println("创建高级款的产品A");
        return new ProductA();
    }

    @Override
    public AbstractProduct createProductB() {
        System.out.println("创建高级款的产品B");
        return new ProductB();
    }

    @Override
    public AbstractProduct createProductC() {
        System.out.println("创建高级款的产品C");
        return new ProductC();
    }
}

package factory_mode.product;

public class SubCreator implements AbstracCreator {
    @Override
    public AbstractProduct createProductA() {
        System.out.println("创建普通款的产品A");
        return new SubProductA();
    }

    @Override
    public AbstractProduct createProductB() {
        System.out.println("创建普通款的产品B");
        return new SubProductB();
    }

    @Override
    public AbstractProduct createProductC() {
        System.out.println("创建普通款的产品C");
        return new SubProductC();
    }
}

抽象工厂写了两次,第一次是接口,解决的是三个产品的问题,第二次是实现,解决的是等级的问题,一个实现类,只解决一个等级的问题,比如说高级。这样就解决了两个因素的抽象工厂的问题了。
经过测试,发现完全可以符合要求,在这里插入图片描述
客户端不知道对象是如何创建出来的,达到了松耦合的作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值