java设计模式-工厂系列

一、简单工厂      

1.背景:

任意定制交通工具的类型和生产过程

代码:

Moveable.java 

package com.cy.dp.factory;

public interface Moveable {
    void run();
}

Car.java:

package com.cy.dp.factory;

public class Car implements Moveable{
    
    @Override
    public void run(){
        System.out.println("car running...");
    }
    
}
View Code

Plane:

package com.cy.dp.factory;

public class Plane implements Moveable{

    @Override
    public void run() {
        System.out.println("plane running...");
    }

}
View Code

VehicleFactory.java:

package com.cy.dp.factory;

/**
 * 交通工具工厂
 * @author CY
 *
 */
public abstract class VehicleFactory {
    abstract Moveable create();
}

CarFactory:

package com.cy.dp.factory;

public class CarFactory extends VehicleFactory{

    @Override
    Moveable create() {
        return new Car();
    }
}
View Code

PlaneFactory:

package com.cy.dp.factory;

public class PlaneFactory extends VehicleFactory{

    @Override
    Moveable create() {
        return new Plane();
    }
}
View Code

Test测试类:

package com.cy.dp.factory;

public class Test {
    public static void main(String[] args) {
        VehicleFactory factory = new CarFactory();
        Moveable m = factory.create();
        m.run();
    }
}
View Code

 

question:
要不要把工厂VehicleFactory设计成接口?
答:可以,接口和抽象类其实是一回事;什么时候用抽象类,什么时候用接口?基本上可以采用这样的方式:如果说这个概念在我们脑中确确实实存在的,那你就用抽象类;如果说这个概念仅仅是某些方面的一个特性,比如说会飞的,能跑的,像这一类的东西,我们就把它设计成接口;如果是比较模糊的概念,不知道设计成抽象类还是接口时,那么设计成接口,原因是我们实现了这个接口之后,还可以从其他的抽象类来继承,更灵活。
 

二、抽象工厂          

 

控制一系列产品(车、武器、食品...)的替换,举个例子,家里搞装修,现在海尔卖那种整体厨房,油烟机、地板、热水器、微波炉...等等,你能不能够做到我要把一系列产品替换掉的话,它就全替换掉了。这件事情该怎么做呢?
 
代码:
Vechile:
package com.cy.dp.factory;

//交通工具
public abstract class Vehicle {
    abstract void run();
}
View Code

Weapon:

package com.cy.dp.factory;

//武器
public abstract class Weapon {
    abstract void shoot();
}
View Code

Food:

package com.cy.dp.factory;

//食物
public abstract class Food {
    abstract void printName();
}
View Code

Car: 

package com.cy.dp.factory;

public class Car extends Vehicle{
    
    public void run(){
        System.out.println("car running...");
    }
    
}
View Code

AK47:

package com.cy.dp.factory;

public class AK47 extends Weapon{
    public void shoot(){
        System.out.println("shooting...");
    }
}
View Code

Apple:

package com.cy.dp.factory;

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

AbstractFactory:

package com.cy.dp.factory;

public abstract class AbstractFactory {
    abstract Vehicle createVehicle();
    abstract Weapon createWeapon();
    abstract Food createFood();
}

DefaultFactory:(默认工厂,生产汽车、AK47、苹果)

package com.cy.dp.factory;

public class DefaultFactory extends AbstractFactory{

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

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

    @Override
    Food createFood() {
        return new Apple();
    }
}

Test:

package com.cy.dp.factory;

public class Test {
    public static void main(String[] args) {
        AbstractFactory f = new DefaultFactory();
        Vehicle v = f.createVehicle();
        v.run();
        Weapon w = f.createWeapon();
        w.shoot();
        Food a = f.createFood();
        a.printName();
        
    }
}
View Code

抽奖工厂好处:

 
好处:如果自己对这一系列东西不满意了,添加自己的系列产品,交通工具从Vehicle继承,武器从Weapon继承... 然后再产生自己的工厂,不用再修改自己的代码,只需要改AbstractFactory f = new DefaultFactory()这一个地方;如果写在配置文件里,甚至源代码再也不用变了;只改配置文件就ok;
抽象工厂:是它生产了一系列产品,如果你想换掉一系列产品的时候,或者在这一系列产品基础之上进行扩展,想产生新的系列产品以及想对这一系列产品的生产过程进行控制,用抽象工厂。
 
 
比较上面两种简单工厂和抽象工厂:
 
问:抽象工厂和普通的工厂比较,有哪些好的和不好的?
对于普通的工厂来说,可以在产品这个维度进行扩展,可以扩展产品,扩展生产产品的工厂;如果在普通工厂里面产生产品系列,就会很麻烦,比如扩展apple,就要多一个appleFactory,最后就发现工厂泛滥;所以普通的工厂方法来说最后会产生工厂泛滥这种问题;
但是对于抽象工厂来说,也有短处,不能扩展新的产品品种,比如上面有Food、Vehicle、Weapon,想要加一个盔甲,那么AbstractFactory就要加一个create盔甲的抽象方法,所有继承AbstractFactory的类也要加实现,就太麻烦了;
 
 
三、spring的bean工厂  
模拟spring的bean工厂:
 
代码:
BeanFactory:
package com.bjsxt.spring.factory;

public interface BeanFactory {
    Object getBean(String id);
}

ClassPathXmlApplicationContext:

package com.bjsxt.spring.factory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

public class ClassPathXmlApplicationContext implements BeanFactory  {
    private Map<String, Object> container = new HashMap<String, Object>();
    
    public ClassPathXmlApplicationContext(String fileName) throws Exception{
        SAXBuilder sb = new SAXBuilder();
          Document doc = sb.build(this.getClass().getClassLoader()
                  .getResourceAsStream(fileName));
          Element root = doc.getRootElement();
          List list = XPath.selectNodes(root, "/beans/bean");
          System.out.println(list.size());
          
          for (int i = 0; i < list.size(); i++) { 
           Element bean = (Element) list.get(i);
           String id = bean.getAttributeValue("id");
           String clazz = bean.getAttributeValue("class");
           Object o = Class.forName(clazz).newInstance();
           container.put(id, o);
           System.out.println(id + " " + clazz);
          }

    }
    
    @Override
    public Object getBean(String id) {
        
        return container.get(id);
    }

}

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans>

  <bean id="v" class="com.bjsxt.spring.factory.Train">
  </bean>
  
  <!--  //v=com.bjsxt.spring.factory.Car  -->


</beans>

Car:

package com.bjsxt.spring.factory;


public class Car implements Moveable{
    
    
    
    public void run() {
        System.out.println("car running.......");
    }
}
View Code

Test测试类:

package com.bjsxt.spring.factory;

import java.io.IOException;
import java.util.Properties;

public class Test {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws Exception {
        BeanFactory f = new ClassPathXmlApplicationContext("com/bjsxt/spring/factory/applicationContext.xml");
        Object o = f.getBean("v");
        Moveable m = (Moveable)o;
        m.run();
    }

}

 

 
 
 
 
 
posted on 2018-06-11 21:29  有点懒惰的大青年  阅读(181)  评论(0编辑  收藏  举报