博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

设计模式——工厂模式

Posted on 2019-12-06 17:27  心默默言  阅读(203)  评论(0编辑  收藏  举报

1.静态工厂方法

只给司机一辆车

package com.bjsxt.dp.factory;

import java.util.ArrayList;
import java.util.List;

public class Car {
    private static Car car = new Car();// 单例
    private static List<Car> cars = new ArrayList<Car>();// 多例。连接池就是

    private Car() {

    }

    /**
     * 静态工厂方法,在一个方法里面控制了产生对象的逻辑,都可以把该方法称为工厂相关的方法,又因为该方法是静态的,所以叫静态工厂方法
     * 
     * @return
     */
    public static Car getInstance() {

        return car;
    }

    public void run() {
        System.out.println("冒着烟奔跑中car...");
    };
}
package com.bjsxt.dp.factory;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Car car = Car.getInstance();
        Car car2 = Car.getInstance();
        if(car==car2)
            System.out.println("same car");
        car.run();

    }

}

2.简单工厂模式

1.目标:要控制任意定制交通工具的类型和生产过程

目标有两层意思(1)任意类型 (2)生产模式,所以对应的,要这两个层面上抽象(Movable,VehicleFactory),利用接口,实现多态

2.类结构

1.Interface Movable.java

2.Car.java

3.Plane.java

4.Interface VehicleFactory.java

5.CarFactory.java

6.PlaneFactory.java

3.代码

1.Movable.java

package com.bjsxt.dp.factory;

public interface Moveable {
    void run();
}

2.Car.java

package com.bjsxt.dp.factory;

public class Car implements Moveable {

    @Override
    public void run() {
        System.out.println("冒着烟奔跑中car...");
    };
}

3.Plane.java

package com.bjsxt.dp.factory;

public class Plane implements Moveable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("扇着翅膀前进中...");
    }

}

4.VehicleFactory.java

package com.bjsxt.dp.factory;

public abstract class VehicleFactory {
    abstract Moveable create();
}

5.CarFactory.java

package com.bjsxt.dp.factory;

public class CarFactory extends VehicleFactory{

    @Override
    public Moveable create() {
        // TODO Auto-generated method stub
        return  new Car();
    }

}

6.PlaneFactory.java

package com.bjsxt.dp.factory;

public class PlaneFactory extends VehicleFactory {

    @Override
    Moveable create() {
        // TODO Auto-generated method stub
        return new Plane();
    }

}

7.Test.java

package com.bjsxt.dp.factory;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        VehicleFactory factory = new CarFactory();
        Moveable m = factory.create();
        m.run();
    }
}

 

 

 

这样系统就可以产生扩展,既可以扩展交通工具,又可以控制生产过程。

public class Broom implements Moveable {
    @Override
    public void run() {
        System.out.println("一路沙尘暴飞奔而来broom...");
    }
}
public class BroomFactory extends VehicleFactory {
    @Override
    Moveable create() {
        return new Broom();
    }
}
public class Test {

    public static void main(String[] args) {
        VehicleFactory factory = new BroomFactory();
        Moveable m = factory.create();
        m.run();
    }

}

3.抽象工厂模式

系列产品(车、武器、食物) 

首先,我们新建了一个Car类,一个AK47类,还有一个Apple类。

package com.bjsxt.dp.abstractFactory;


public class Car {
    public void run() {
        System.out.println("冒着烟奔跑中car...");
    }
}
package com.bjsxt.dp.abstractFactory;

public class AK47 {
    public void shoot(){
        System.out.println("哒哒哒...");
    }
}
package com.bjsxt.dp.abstractFactory;

public class Apple {
    public void printName() {
        System.out.println("apple");
    }
}

然后我们新建一个用户测试类,他有一辆车,一把AK47,一个苹果。

package com.bjsxt.dp.abstractFactory;


public class Test {

    public static void main(String[] args) {
        Car car = new Car();
        car.run();
        AK47 ak47 = new AK47();
        ak47.shoot();
        Apple apple = new Apple();
        apple.printName();
    }

}

 

这里的车,AK47,苹果都是分别new出来的,如果我们想要一次性的定制这些东西就需要用到抽象工厂模式。

 

首先,我们想到要新建一个工厂,取名为DefaultFactory.

package com.bjsxt.dp.abstractFactory;

public class DefaultFactory {

    public Car createCar(){
        return new Car();
    }

    public AK47 createAK47(){
        return new AK47();
    }

    public Apple createApple(){
        return new Apple();
    }
}

 

这样的话我们的用户测试类就可以改成这样:

package com.bjsxt.dp.abstractFactory;


public class Test {

    public static void main(String[] args) {
        DefaultFactory factory = new DefaultFactory();
        Car car = factory.createCar();
        car.run();
        AK47 ak47 = factory.createAK47();
        ak47.shoot();
        Apple apple = factory.createApple();
        apple.printName();
    }
}

 

如果我想把上面的一系列产品都替换掉,只要来一个新的工厂就可以了,如 MagicFactory:

package com.bjsxt.dp.abstractFactory;

public class MagicFactory {
    public Broom createBroom(){
        return new Broom();
    }

    public MagicStick createMagicStrick(){
        return new MagicStick();
    }

    public MushRoom createMushRoom(){
        return new MushRoom();
    }
}

那么现在问题来了,如果我想把测试类中的DefaultFactory换成MagicFactory,那么下面的这些方法也要全部都改,太麻烦了,不想改下面的这些方法怎么办呢?

 

解决方法,产生一个工厂的父类,abstractFactory

package com.bjsxt.dp.abstractFactory;

public abstract class AbstractFactory {
    public abstract Vehicle createVehicle();
    public abstract Weapon createWeapon();
    public abstract Food createFood();
}
package com.bjsxt.dp.abstractFactory;

public abstract  class Vehicle {
    public abstract void  run();
}
package com.bjsxt.dp.abstractFactory;

public abstract class Weapon {
   public abstract void shoot();
}
package com.bjsxt.dp.abstractFactory;

public abstract class Food {
    public abstract void printName();
}

有了上面的这些抽象类,就可以继承上面的这些类。

package com.bjsxt.dp.abstractFactory;

public class DefaultFactory extends AbstractFactory{


    @Override
    public Vehicle createVehicle() {
        return new Car();
    }

    @Override
    public Weapon createWeapon() {
        return new AK47();
    }

    @Override
    public Food createFood() {
        return new Apple();
    }
}
package com.bjsxt.dp.abstractFactory;

public class MagicFactory extends AbstractFactory {
    @Override
    public Vehicle createVehicle() {
        return new Broom();
    }

    @Override
    public Weapon createWeapon() {
        return new MagicStick();
    }

    @Override
    public Food createFood() {
        return new MushRoom();
    }
}

 

package com.bjsxt.dp.abstractFactory;

public class AK47 extends Weapon{
    public void shoot(){
        System.out.println("哒哒哒...");
    }
}
package com.bjsxt.dp.abstractFactory;

public class Apple extends Food{
    public void printName() {
        System.out.println("apple");
    }
}
package com.bjsxt.dp.abstractFactory;


public class Car extends Vehicle {
    @Override
    public void run() {
        System.out.println("冒着烟奔跑中car...");
    }
}

 

package com.bjsxt.dp.abstractFactory;


public class Broom extends Vehicle {
    @Override
    public void run() {
        System.out.println("一路沙尘暴飞奔而来broom...");
    }
}
package com.bjsxt.dp.abstractFactory;

public class MushRoom extends Food{
    @Override
    public void printName() {
        System.out.println("mushroom...");
    }
}
package com.bjsxt.dp.abstractFactory;

public class MagicStick extends Weapon {
    @Override
    public void shoot() {
        System.out.println("fire hu hu");
    }
}

 

test类

package com.bjsxt.dp.abstractFactory;


public class Test {

    public static void main(String[] args) {
        AbstractFactory factory = new DefaultFactory();
//        AbstractFactory factory = new MagicFactory();
        Vehicle v = factory.createVehicle();
        v.run();
        Weapon w = factory.createWeapon();
        w.shoot();
        Food f = factory.createFood();
        f.printName();
    }
}

整个体系结构如下图:

 

如游戏里面的换皮肤功能,如果换个皮肤,界面上的很多功能及按钮都变了。

总结:抽象工厂是生产了一系列产品,如果想换掉这一系列产品的时候,或者是想在这一些列产品的功能上进行扩展,想产生新的系列产品以及想对这一系列产品的生产过程进行控制,用抽象工厂。 

简单工厂的问题在于产生产品系列的时候会造成工厂泛滥,而抽象工厂的问题在于在产生新的产品品种的时候,改动的地方会很多。

4.Spring中的工厂

现在又一个moveable接口,有两个实现类。

package com.bjsxt.dp.springfactory;

public interface Moveable {
    void run();
}
package com.bjsxt.dp.springfactory;


public class Car implements Moveable {
    public void run() {
        System.out.println("冒着烟奔跑中car...");
    }
}
public class Train implements Moveable {
    @Override
    public void run() {
        System.out.println("小火车呜呜呜");
    }
}

此时,可以在测试类中,new car()或者new train().

public class Test {
    public static void main(String[] args) throws Exception {

//        Moveable m = new Train();
        Moveable m = new Car();
        m.run();
    }
}

现在的问题是能不能不要new,因为new源代码还是要更改,能不能改到配置文件里。

1.利用properties文件配置

VehicleType=factory.Train
package factory;

import factory.Car;
import factory.Moveable;

import java.util.Properties;

public class Test {
    public static void main(String[] args) throws Exception {
        Properties pros = new Properties();
        pros.load(Test.class.getClassLoader().getResourceAsStream("spring.properties"));
        String vehicleTypeName = pros.getProperty("VehicleType");
        System.out.println(vehicleTypeName);
        Object o = Class.forName(vehicleTypeName).newInstance();
        Moveable m = (Moveable)o;
        m.run();
    }
}

 

 

此时,要是想改成car,则只要改配置文件就可以了。VehicleType=factory.Car

2.spring中的Bean工厂

1.先导入spring的jar包及spring框架需要的logging jar包

 

 

 

 

 

 

2.spring中的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <bean id="v" class="com.bjsxt.dp.springfactory.Car">
  </bean>
  <!-- 相当于 //v=com.bjsxt.spring.factory.factory.Car  -->

</beans>

3.测试类

package com.bjsxt.dp.springfactory;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        BeanFactory f = new ClassPathXmlApplicationContext("applicationContext.xml");
        Object o = f.getBean("v");
        Moveable m = (Moveable) o;
        m.run();
    }
}