设计模式—创建者模式之工厂模式

1. 看一个问题(引入)

假设现在有一个接口,有一个实现类实现了它,客户端怎么使用它呢?
在这里插入图片描述
如图,首先创建一个实例BaseApiImpl,赋值给一个BaseApi接口类型的变量,通过这个变量来操作接口。
代码如下:

public interface BaseApi {
    public void testString(String s);
}

public class BaseApiImpl implements BaseApi{
    @Override
    public void testString(String s) {
        System.out.println("string是:"+s);
    }
}

public class Client {
    public static void main(String[] args) {
        /**
         * 不符合接口隔离原则
         */
        BaseApi baseApi = new BaseApiImpl();//在Client可以直接看见接口和实现类
        baseApi.testString("我是XXX");
    }
}

思考:

  1. 上述代码实先了这样一个功能,但是又一个问题,就是在Client客户端可以直接看见接口和实现类,不符合接口隔离原则
  2. 怎么改进呢?也许可以new BaseApiImpl()移入工厂内。

2. 简单工厂模式

以上,假设现在有一个水果店,买苹果和香蕉,怎么实现呢。
在这里插入图片描述
如类图,

  1. 我们可以创建一个抽象接口FruitApi,在实现这样一个接口。
  2. 每一个产品对应一个具体类,如Apple、Banana。
  3. 创建一个具体的工厂,将new Apple()、new Banana()移入工厂内
  4. 客户端Client使用。
    代码如下:
//抽象接口FruitApi
public interface FruitApi {
    public void sell(String s);
}
//具体类Apple
public class Apple implements FruitApi {
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是苹果");
    }
}
//具体类 Banana
public class Banana implements FruitApi{
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是香蕉");
    }
}
//具体工厂Factory
public class Factory {
    public static FruitApi getFruitService(int condition){
        FruitApi fruitApi = null;
        if (condition == 1) {
            fruitApi = new Apple();
        }else if (condition == 2) {
            fruitApi = new Banana();
        }
        return fruitApi;
    }
}
//客户Client
public class Client {
    public static void main(String[] args) {
        FruitApi fiurtApi = Factory.getFruitService(1);
        fiurtApi.sell("我正在买水果:");
    }
}

思考:

  1. 相较与开始的问题导入,简单工厂模式中客户端不知道具体实现的是什么,只需要通过工厂获取一个接口对象,通过操作接口对象来实现自己想要的功能。
  2. 但是当需要新增产品时,比如要买菠萝,那么就需要修改Factory中的代码,不符合开闭原则。

3.工厂方法模式

基于以上思考,就有了工厂方法模式。
在这里插入图片描述如类图,

  1. 我们在第简单工厂模式的基础上加入了一个抽象工厂Factory。
  2. 每一个产品对应一个具体的工厂类如AppleFactory、BananaFactory
    代码如下:
//抽象接口FruitApi
public interface FruitApi {
    public void sell(String s);
}
//具体类Apple
public class Apple implements FruitApi {
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是苹果");
    }
}
//具体类 Banana
public class Banana implements FruitApi{
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是香蕉");
    }
}
//抽象工厂Factory
public interface Factory {
    FruitApi sellFruit();
}
//具体工厂AppleFactory 
public class AppleFactory implements Factory{
    @Override
    public FruitApi sellFruit() {
        return new Apple();
    }
}
//具体工厂BananaFactory 
public class BananaFactory implements Factory{
    @Override
    public FruitApi sellFruit() {
        return new Banana();
    }
}
//客户Client
public class Client {
    public static void main(String[] args) {
        Factory factory = new BananaFactory();
        factory.sellFruit().sell("我买了水果:");
        Factory factory1 = new AppleFactory();
        factory1.sellFruit().sell("我买了水果:");
    }
}

思考:

  1. 一般工厂方法返回的是被创建对象的接口对象,在设计的时候,不需要考虑抽象工厂具体的功能,只要在用的时候返回需要的对象即可。
  2. 如果要加入一个新的产品(菠萝),只需要新建一个菠萝具体类和菠萝具体工厂,不需要改变抽象工厂。
  3. 假设现在我需要加入一个新的产品簇,比如水果汁,我该怎么实现呢?

4.抽象工厂模式

基于以上思考。
在这里插入图片描述
如类图:

  1. 在工厂方法模式的基础上添加一个新的产大类JuiceApi
  2. 同样每一个产品对应一个实现类AppleJuice、BananaJuice
  3. 在抽象工厂以及具体工厂类中添加相应的代码。

代码如下:

//抽象接口FruitApi
public interface FruitApi {
    public void sell(String s);
}
//具体类Apple
public class Apple implements FruitApi {
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是苹果");
    }
}
//具体类 Banana
public class Banana implements FruitApi{
    @Override
    public void sell(String s) {
        System.out.println(s+"我买的是香蕉");
    }
}
//抽象接口JuiceApi 
public interface JuiceApi {
    void sellJuice(String s);
}
//具体类 AppleJuice 
public class AppleJuice implements JuiceApi {
    @Override
    public void sellJuice(String s) {
        System.out.println(s+"我买的是苹果汁");
    }
}
//具体类 BananaJucie 
public class BananaJucie implements JuiceApi{
    @Override
    public void sellJuice(String s) {
        System.out.println(s+"我买的是苹果汁");
    }
}
//抽象工厂Factory
public interface Factory {
    FruitApi sellFruit();
    JuiceApi sellJuice();
}
//具体工厂AppleFactory 
public class AppleFactory implements Factory{
    @Override
    public FruitApi sellFruit() {
        return new Apple();
    }
    @Override
    public JuiceApi sellJuice() {
        return new AppleJuice();
    }
}
//具体工厂BananaFactory 
public class BananaFactory implements Factory{
    @Override
    public FruitApi sellFruit() {
        return new Banana();
    }
    @Override
    public JuiceApi sellJuice() {
        return new BananaJucie();
    }
}
//客户Client
public class Client {
    public static void main(String[] args) {
        Factory factory = new BananaFactory();
        factory.sellFruit().sell("我买了水果:");
        Factory factory1 = new AppleFactory();
        factory1.sellFruit().sell("我买了水果:");
    }
}

思考:

  1. 抽象工厂模式为一系列的相关对象(产品簇)创建一个接口
  2. 但是当需要新增一个产品簇的时候,需要修改抽象工厂以及所有具体工厂的代码,从这个方面上讲,不符合开闭原则。

5.总结

  1. 简单工厂模式就是创建了多个实例化的类。
  2. 工厂方法模式相较与简单工厂模式,加了一个抽象工厂的概念。一个产品对应一个具体的工厂类。
  3. 抽象工厂模式相较与工厂方法模式,在工厂方法模式的基础上添加了一个产品簇。但是当需要在添加一个新的产品簇的时候,需要修改抽象工厂以及所有具体工厂类的代码,违反开闭原则。
  4. 当抽象工厂模式的产品簇只有一种时,即为工厂方法模式。抽象工厂模式是工厂方法模式的一种拓展
  5. 设计模式只是一种指导思想,具体使用哪种,根据实际情况来进行分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值