设计模式--工厂方法

工厂方法模式

主要用于生成复杂对象,如果只通过new就可以完事,就不用该模式。这个模式看起来简单,但感觉很难理解,不晓得存在的意义是什么,都知道子类名称了为什么不直接new(或许是实际创建比较复杂,例子都偷懒使用简单的类型,所以可以直接new就完成对象创建了)都拿到Class 自己通过反射也可以直接拿到对象实例,和在工厂中使用反射生成有什么区别?

工厂一般来说都生成一类相似的产品,比如说罐头工厂,生产黄桃罐头、杨梅罐头、凤梨罐头。客户通过工厂对外的接口来获得自己想要的产品。

  • 对客户而言,需要知道这个产品能干什么(抽象产品接口)已经从哪里获得(抽象工厂接口)自己想要的(传入参数表明自己意图)产品。
  • 对于工厂而言,需要实现具体生产组装产品的细节,还需要了解客户意图,使用具体对应工厂,返回具体产品。

主要角色

  • 抽象工厂:工厂模式的核心
  • 具体工厂:实现具体逻辑
  • 抽象产品:是工厂所生产产品的基类,规定了这些产品的公共特征
  • 具体产品: 实现抽象产品的某个具体类

具体实现

这里有两种实现方案,第一种使用泛型,也是让我困惑的方式。第二种使用字符串或枚举实现

1.泛型方式

  • 抽象产品
public abstract class AudiCar {
    public abstract void drive();
    public abstract void selfNavigation();
}
  • 具体产品
public class AudiQ3 extends AudiCar {
    @Override
    public void drive() {
        System.out.println("Q3 启动了");
    }
    @Override
    public void selfNavigation() {
        System.out.println("Q3 开始自动巡航!");
    }
}

public class AudiQ5 extends AudiCar {
    @Override
    public void drive() {
        System.out.println("Q5 启动了!");
    }
    @Override
    public void selfNavigation() {
        System.out.println("Q5 开启自动巡航!");
    }
}

public class AudiQ7 extends AudiCar {
    @Override
    public void drive() {
        System.out.println("Q7 启动了!");
    }
    @Override
    public void selfNavigation() {
        System.out.println("Q7 开启自动巡航!");
    }
}
  • 抽象工厂
public abstract class AudiFactory {
    public abstract <T extends AudiCar> T createAudiCar(Class<T> T);
}
  • 具体工厂
public class AudiCarFactory extends AudiFactory {
    @Override
    public <T extends AudiCar> T createAudiCar(Class<T> clz) {
        AudiCar car=null;
        try {
            car= (AudiCar) Class.forName(clz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) car;
    }
}
  • 客户端使用
public class Client {
    public static void main(String[] args) {
        AudiFactory audiFactory = new AudiCarFactory();
        AudiCar audiCarq3 = audiFactory.createAudiCar(AudiQ3.class);
        AudiCar audiCarq5 = audiFactory.createAudiCar(AudiQ5.class);
        AudiCar audiCarq7 = audiFactory.createAudiCar(AudiQ7.class);

        audiCarq3.drive();
        audiCarq3.selfNavigation();
        audiCarq5.drive();
        audiCarq5.selfNavigation();
        audiCarq7.drive();
        audiCarq7.selfNavigation();
    }
}

这种方式客户端都已经用到“实现类.class”了,客户端都其实已经知道了具体产品类的实现细节。

2.使用约定名称或枚举

  • 抽象产品
public interface Can {
    void open();
    String createDate();
}
  • 具体产品
public class PeachCan implements Can {
    public PeachCan() {  }
    @Override
    public void open() {
        System.out.println("PeachCan被打开!");
    }
    @Override
    public String createDate() {
        return null;
    }
}

public class BayberryCan implements Can{
    public BayberryCan() { }
    @Override
    public void open() {
        System.out.println("Bayberry 被打开了!");
    }
    @Override
    public String createDate() {
        return null;
    }
}

public class AnanasCan implements Can {
    public AnanasCan() {  }
    @Override
    public void open() {
        System.out.println("Ananas被打开了!");
    }
    @Override
    public String createDate() {
        return null;
    }
}

  • 抽象工厂
public interface Factory {
    Can getCan(String canName);
    Can getCan(CanTypes type);
    void doSomething();
}
  • 具体工厂
public class CanFactory implements Factory {
    public CanFactory() {  }

    @Override
    public Can getCan(String canName) {
        if (canName.isEmpty()) {
            return null;
        }
        if (canName.equals("peach")) {
            return new PeachCan();
        } else if (canName.equals("bayberry")) {
            return new BayberryCan();
        } else if (canName.equals("ananas")) {
            return new AnanasCan();
        } else {
            return null;
        }
    }

    @Override
    public Can getCan(CanTypes type) {
        switch (type) {
            case PEACH:
                return new PeachCan();
            case ANANAS:
                return new AnanasCan();
            case BAYBERRY:
                return new BayberryCan();
            default:
                return null;
        }
    }

    @Override
    public void doSomething() {
        System.out.println("工厂 doSomething");
    }
}
  • 约定枚举
public enum CanTypes {
    PEACH,
    BAYBERRY,
    ANANAS;
}

这里使用字符串(张口说“我要个黄桃罐头”)或枚举(看着工厂给的菜单选)更符合实际情况,客户端只需要知道 抽象工厂接口、产品接口,具体产品对应的枚举类。 不需要知道任何具体实现,更符合迪米特原则。

工厂模式更侧重的是如何方便的给和客户端提供产品,而不是具体产品的组装。

Call接口提供了内部接口Factory(用于将对象的创建延迟到该工厂类的子类中进行,从而实现动态的
配置,工厂方法模式。(工厂方法模式:这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值