设计模式-创建型之工厂模式

前言
  • 工厂模式
    – 我们通常是通过 new 来进行创建对象,这样导致程序的耦合性很高,而工厂模式就是用于代替直接 new 的一种模式。
  • 三种工厂模式
    – 简单工厂模式:用工厂类代替 new ,降低类之间的耦合度;
    – 工厂方法模式:将具体的处理交给子类;用于生产某一类产品;
    – 抽象工厂模式:用于生产一系列产品;
简单工厂(静态工厂)
  • 现在有一需求(举例),需要生产一些java开发工具,如Idea,Eclipse等。
  • UML设计图如下
    在这里插入图片描述
  • 代码实现
//简单工厂
public class SimpleFactory {

    /**
     * 使用的是简单的静态工厂模式
     * @param type
     * @return
     */
    public static Product createProduct(String type){
        Product product = null;

        if(type.equals("idea")){
            product = new IdeaProduct();
        }else if(type.equals("eclipse")){
            product = new EclipseProduct();
        }
        return product;
    }
}
//产品父类
public abstract class Product {

    private String name;
    
    public abstract void user();
}
//产品子类
public class IdeaProduct extends Product{
    @Override
    public void user() {
        System.out.println("使用IDEA产品");
    }
}
//产品子类
public class EclipseProduct extends Product {
    @Override
    public void user() {
        System.out.println("使用eclipse产品");
    }
}
  • 使用
public class Test {
    public static void main(String[] args) {
        Product idea = SimpleFactory.createProduct("idea");
        idea.user();
        Product eclipse = SimpleFactory.createProduct("eclipse");
        eclipse.user();
    }
}
  • 总结
    特点:用于生产单个产品,将生产产品的逻辑封装在工厂类中;
    优点:去除客户端(上面的Test类)与具体产品的依赖,客户端无需关系产品生产细节;
    缺点:添加新产品需要修改工厂类,违背开闭原则;比如添加一个STS开发工具,需要在工厂类中添加新的判断;
工厂方法模式
  • 分析:==抽象的本质是不考虑具体怎么实现,而是仅关注接口。==所以我们可以对简单工厂进一步抽象,简单工厂是违背了开闭原则,开闭原则的一种体现就是把打破开闭原则的地方进行抽象(利用接口或者抽象类),在上面例子中根据不同的条件创建不同的对象,我们可以将具体创建对象的工作交给子类来完成。
  • UML设计图如下
  • 代码实现
//抽象工厂
public abstract class Factory {
    public abstract Product createProduct();
}
//工厂子类
public class IdeaFactory extends Factory {
    @Override
    public Product createProduct() {
        return new IdeaProduct();
    }
}
//工厂子类
public class EclipseFactory extends Factory {
    @Override
    public Product createProduct() {
        return new EclipseProduct();
    }
}
//产品抽象类
public abstract class Product {
    public abstract void user();
}
//产品子类
public class IdeaProduct extends Product {
    @Override
    public void user() {
        System.out.println("使用IDEA开发");
    }
}
//产品子类
public class EclipseProduct extends Product {
    @Override
    public void user() {
        System.out.println("使用Eclipse开发");
    }
}
  • 使用
public class Test {

    public static void main(String[] args) {
        Factory ideafactory = new IdeaFactory();
        Product idea = ideafactory.createProduct();
        idea.user();
        Factory eclipseFactory = new EclipseFactory();
        Product eclipse = eclipseFactory.createProduct();
        eclipse.user();
    }
}
  • 第二种优化方式(其实也是对抽象工厂模式的优化)
//抽象工厂:使用泛型(其实也是一种抽象);使用反射
public abstract class AbstractFactory {
	//使用 extends :给泛型类型一个约束,从而限定只能返回 Product 类型对象 
    public abstract <T extends Product> T createProduct(Class<T> clzz) throws Exception;
}
//具体工厂实现
public class ConcreteFactory extends AbstractFactory {
    @Override
    public <T extends Product> T createProduct(Class<T> clzz) throws Exception {
        T instance = (T) Class.forName(clzz.getName()).newInstance();
        return instance;
    }
}
//调用
public class Test {
    public static void main(String[] args) {
        AbstractFactory factory = new ConcreteFactory();
        try {
            Product product = factory.createProduct(EclipseProduct.class);
            product.user();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 总结
    特点:生产某一类类型产品;一种产品对应一个工厂类;具体实现交给子类;其实工厂方法模式的定义更偏向于在父类中定义产品生产的流程(算法),而具体的实现交给子类实现。
//示例代码
public abstract class Factory {
    public abstract Product createProduct();
    public abstract void register(Product product);
    //final 定义方法无法被重载,子类只需提供抽象方法的实现
    public final Product create(){
        Product product = createProduct();
        register(product);
        return product;
    }
}

优点:添加新产品只需添加相应工厂类,符合开闭原则、里氏替换原则;
缺点:产品多时,工厂泛滥;

抽象工厂模式
  • 个人理解,抽象工厂模式与工厂方法模式在形式上没有什么区别,但在侧重点上有一些区别,工厂方法侧重于:更偏向于在父类中定义产品生产的流程(算法),而具体的实现交给子类实现。而抽象工厂侧重于生产零件并将零件组装成产品,其实也可把零件当成一种产品;
  • 代码实现
    代码出处: https://blog.csdn.net/michael_yt/article/details/82112443
//1.抽象工厂
public abstract class CarFactory {
    /**
     * 生产轮胎
     * 
     * @return 轮胎
     * */
    public abstract ITire createTire();

    /**
     * 生产发动机
     * 
     * @return 发动机
     * */
    public abstract IEngine createEngine();

    /**
     * 生产制动系统
     * 
     * @return 制动系统
     * */
    public abstract IBrake createBrake();

}

//2.三个产品抽象接口
public interface ITire {
    /**
     * 轮胎 
     */
    void tire();
}

public interface IEngine {
    /**
     *发动机 
     */
    void engine();
}

public interface IBrake {
    /**
     *制动系统 
     */
    void brake();
}

//3.根据抽象接口定义不同的对象
public class NormalBrake implements IBrake{
    @Override
    public void brake() {
        System.out.println("普通制动");
    }
}
public class SeniorBrake implements IBrake{
    @Override
    public void brake() {
        System.out.println("高级制动");
    }
}  //后面的定义省略。。。。。。。。。。。。。

//4.实现具体的工厂类
public class Q3Factory extends CarFactory{

    @Override
    public ITire createTire() {
        return new NormalTire();
    }

    @Override
    public IEngine createEngine() {
        return new DomesticEngine();
    }

    @Override
    public IBrake createBrake() {
        return new NormalBrake();
    }
}

//5.客户端使用
public class Client {
    public static void main(String[] args) {
        CarFactory factoryQ3 = new Q3Factory();
        factoryQ3.createTire().tire();
        factoryQ3.createEngine().engine();
        factoryQ3.createBrake().brake();
        System.out.println("---------------");
    }
}

比如各种数据库的SqlSessionFactory,其实都使用了抽象工厂模式;

  • 总结:
    特点:用于生产多种零件(产品);
    优点:添加新产品只需添加相应工厂类,符合开闭原则、里氏替换原则;
    缺点:新增零件时,所有工厂类都需要修改(不知是我理解不够还是本质就是这样,我觉得抽象工厂模式不是很优雅)
多说一点
  • 上面代码中,工厂父类(除简单工厂)也都可以定义为接口;
  • 下面这种优化模式很值得去回味(代码再写一遍),上面说这也是抽象工厂的一种优化:我们可以把所有零件都定义为’Product’ 类类型或者空接口(更倾向于接口,扩展性更高)或者简单直接使用泛型 T,然后利用反射创建对象,你会发现这个方法就可以为你创建所有的零件(产品),这看起来很优雅。
//抽象工厂:使用泛型(其实也是一种抽象);使用反射创建对象
public abstract class AbstractFactory {
	//使用 extends :给泛型类型一个约束,从而限定只能返回 Product 类型对象 
    public abstract <T extends Product> T createProduct(Class<T> clzz) throws Exception;
}
//具体工厂实现
public class ConcreteFactory extends AbstractFactory {
    @Override
    public <T extends Product> T createProduct(Class<T> clzz) throws Exception {
        T instance = (T) Class.forName(clzz.getName()).newInstance();
        return instance;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值