设计模式之-工厂模式

简单工厂模式

简单工厂模式属于创建型模式,定义一个创建对象的类,由这个类来封装实例化对象的代码,在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.

下面举例说一下

  • 这是初始代码
//抽象产品
interface Food{
    void eat();
}

//具体产品
class HanBao implements  Food{

    @Override
    public void eat() {
        System.out.println("吃汉堡咯!");
    }
}
//作者
// #########################################################
//用户

public class Client {

    public static void main(String[] args) {
        Food food = new HanBao(); //向上转型
        food.eat();
    }

}

我们会发现一个问题,这种代码非常脆弱!比如作者修改了具体的产品类名,那么客服端代码也要随之改变,这样的代码,客户端和服务端的代码是耦合的,违法了依赖倒置原则
改善: 解耦 无论服务器端代码怎么修改,客服端代码不关注它的变化,也不用动我的客服端代码-》 使用简单工厂模式,代码如下

// 针对于之前的问题:服务器代码一旦修改,客服端代码也要跟着修改
    //修改代码如下: 使用简单工厂(作者做的)设计模式

//抽象产品
interface Food{
    void eat();
}

//具体产品
class HanBao2 implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡咯!");
    }
}

class TasteShrimp implements  Food{

    @Override
    public void eat() {
        System.out.println("口味虾真好吃");
    }
}

//食物工厂
class FoodFactory{
    public static Food getFood(String type) {
        Food food = null;
        switch (type){
            case "汉堡":
                food = new HanBao2();
                break;
            case "口味虾":
                food = new TasteShrimp();
                break;

        }
        return food;
    }
}


// 客户端================================================================

public class Client {

    public static void main(String[] args) {
        Food food = FoodFactory.getFood("汉堡");
        food.eat();
}
}

简单工厂
优点:
1. 具体产品的类型 从客服端代码中解耦出来 松耦合
2. 服务器端代码修改了具体产品类名,客服端不知道,这便符合我们的“面向接口编程”的思想
这里的接口不单包括了 interface 只要是下层给上层暴露出来的 方法/类 都可以认为是 面向接口编程里面的接口形式

缺点:
1. 要记住 type与具体产品的映射关系
2. 如果具体产品非常多,简单工厂的代码就会变得非常臃肿
3. 最重要的是,如果要扩展具体产品,那么势必会修改简单工厂的代码,违反了 “开闭原则”
4. 始终丢失原始类型
Calendar calendar = Calendar.getInstance();
怎么解决–》 工厂方法

工厂方法

又称工厂模式、多态工厂模式和虚拟构造器模式。将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

代码如下

//抽象产品
interface Food {
    void eat();
}

//具体产品角色
class HanBao implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡咯!");
    }
}

//产品
class TasteShrimp1 implements Food {

    @Override
    public void eat() {
        System.out.println("口味虾真好吃");
    }
}

//定义食物生产工厂   --》 专门生产食物  --?知不知道具体生产那个具体产品?
interface FoodFactory {
    public Food getFood();
}

//具体产品工厂
class HanBaoFactory implements FoodFactory {

    @Override
    public Food getFood() {
        return new HanBao();
    }
}

class TasteShrimpFactory implements FoodFactory {

    @Override
    public Food getFood() {
        return new TasteShrimp1();
    }
}
//现在开始变化  扩展新产品烧卖
class Sumai implements  Food{

    @Override
    public void eat() {
        System.out.println("我一个气能吃十个烧卖。。。");
    }
}
//具体的烧卖工厂
// 我没动上面的源代码  扩展了产品和产品工厂
class SumaiFactory1 implements FoodFactory{

    @Override
    public Food getFood() {
        return new Sumai();
    }
}
//  =====================================
public class Client {

    public static void main(String[] args) {

        //  不要直接new HanBao() 直接new就与具体类名耦合,作为上层不应该知道下层内容的
        FoodFactory ff = new SumaiFactory1();
        //  调的子类的方法
        Food food = ff.getFood();

        food.eat();

    }

优点:

  1. 有简单工厂的优点 符合开闭
  2. 扩展了新产品,不需要修改作者原来的代码,只是扩展了一个新工厂而已

思考:

抽象工厂模式

	定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类	
	抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
	将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
  1. 抽象工厂版本1
// 现在提出业务需求,   多个产品等级
//抽象产品
interface Food {
    void eat();
}

//具体产品角色
class HanBao implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡咯!");
    }
}

class TasteShrimp implements Food {

    @Override
    public void eat() {
        System.out.println("口味虾真好吃");
    }
}

// 添加产品等级
interface Drink {
    public void drink();
}

//新增具体产品
class Cola implements Drink {

    @Override
    public void drink() {
        System.out.println("可乐好喝。。");
    }
}
// 啤酒
class Beer implements Drink {

    @Override
    public void drink() {
        System.out.println("夏天喝啤酒最爽了。。");
    }
}

interface FoodFactory {
    public Food getFood();
}


class HanBaoFactory implements FoodFactory {

    @Override
    public Food getFood() {
        return new HanBao();
    }


}


class TasteShrimpFactory implements FoodFactory {

    @Override
    public Food getFood() {
        return new TasteShrimp();
    }

}

// 饮料工厂
interface DrinkFactory {
    public Drink getDrink();
}

class ColaFactory implements DrinkFactory {

    @Override
    public Drink getDrink() {
        return new Cola();
    }
}

class BeerFactory implements DrinkFactory {

    @Override
    public Drink getDrink() {
        return new Beer();
    }
}

//=+======================================
//用户
public class Client {

    public static void main(String[] args) {


    }
}

上述代码有几个问题

  • 每增加一个产品等级 就要增加一个生产产品的工厂(DrinkFactory)以及具体的产品生产工厂和具体的产品类 这样会 造成
    类的爆炸式增长,增加了系统复杂度 增加了开销
  • 一个具体工厂只能创建一个具体产品
  • 设计太过于复杂

由以上问题,引出版本二,代码如下

// 针对于工厂方法的问题:当有多个产品等级时(食物、饮料、甜品。。。),工厂类就会很多
//修改代码如下: 使用抽象工厂设计模式

//抽象产品
interface Food{
    void eat();
}

//具体产品角色
class HanBao implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡咯!");
    }
}

class TasteShrimp implements Food {

    @Override
    public void eat() {
        System.out.println("口味虾真好吃");
    }
}
// 添加产品等级
interface Drink{
    public void drink();
}

class Cola implements Drink{

    @Override
    public void drink() {
        System.out.println("可乐好喝。。");
    }
}

class Beer implements Drink{

    @Override
    public void drink() {
        System.out.println("夏天喝啤酒最爽了。。");
    }
}

class XiaoYeFactory implements  Factory{

    @Override
    public Food getFood() {
        return new TasteShrimp();
    }

    @Override
    public Drink getDrink() {
        return new Beer();
    }
}


class KFCFactory implements  Factory{

    @Override
    public Food getFood() {
        return new HanBao();
    }

    @Override
    public Drink getDrink() {
        return new Cola();
    }
}
// 抽象工厂  --》 抽象工厂生产多个产品等级
interface Factory{
    // 本来工厂只生产一个产品等级,现在生产多个产品等级
    public Food getFood();
    public Drink getDrink();

}

class RoastDuck implements  Food{

    @Override
    public void eat() {
        System.out.println("烤鸭吃不腻啊。。");
    }
}

class Fenta implements Drink{

    @Override
    public void drink() {
        System.out.println("芬达越喝越来劲。。");
    }
}
class BeiJingFactory implements  Factory{

    @Override
    public Food getFood() {
        return new RoastDuck();
    }

    @Override
    public Drink getDrink() {
        return new Fenta();
    }
}


// ===================================================
public class Client {
    public static void main(String[] args) {

    }

通过上述代码我们发现:

  • 抽象工厂

    • 优点

      • 仍然拥有简单工厂和工厂方法的优点
      • 更重要的时,抽象工厂把工厂类的数量减少了! 无论有多少个产品等级,工厂就一套
    • 存疑

      • 疑问 为什么夜宵工厂里面,就必须啤酒配口味虾呢?不能随意搭配呢?
      • 解释 抽象工厂中,可以生产多个产品,这多个产品之间必须有逻辑关系
    • 缺点

      • 当产品等级发生变化时(增加产品等级,删除),都要引起所有以前工厂代码的修改,违反了"开闭原则" (影响了其他功能)
    • 结论

      • 当产品等级比较固定时,可以考虑使用抽象工厂
      • 如果产品等价经常变化,则不建议使用抽象工厂

总结

  1. 工厂模式的意义: 将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系解耦,从而提高项目的扩展性和维护性
  2. 设计模式的依赖抽象原则
    1. 创建对象实例时,不要直接new,而是把这个动作放在一个工厂方法中,并放回实例,或者说变量不要直接持有具体类的引用
    2. 不要让类继承类,而是继承抽象类或者实现接口
    3. 不要覆盖基类中已经实现的方法
  3. 创建型模式对调用者来说,隐藏了复杂的逻辑处理过程,流水线生产
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值