您的位置:首页 > 其它

J2EE初级学习——设计模式-工厂模式和单例模式

2018-02-08 13:32 344 查看

1.只给司机一辆车—— 单例模式,多例模式,静态工厂方法

1.1单例模式

这里先建一个Car类,类里面只有一个run方法   
package com.TiHom.factory;

public class Car {
public void run(){
System.out.println("以200码的速度飞驰car......");
}
}
在测试类中
package com.TiHom.factory;

public class Test {
public static void main(String[] args) {
Car c = new Car();
c.run();
}
}

这样的话其实我们可以new很多辆车出来,不能控制这个司机只能开同一辆车,所以接下来就是单例模式的介绍首先,为了让他只能开一辆车,我们会想办法不让他new出新车来,所以会想到私有化实例
package com.TiHom.factory;

public class Car {
private Car(){}

public void run(){
System.out.println("以200码的速度飞驰car......");
}
}

但是测试类中报错了,因为我们没办法在外部进行new,连一开始那辆都没办法提供给他,因此有一个典型的提供调用的方法:
package com.TiHom.factory;

public class Car {
private Car(){}

public static Car getInstance(){  //instance的意思是实例对象,这里表示拿到实例对象
return new Car();
}

public void run(){
System.out.println("以200码的速度飞驰car......");
}
}

这里依然不能限制司机去通过getInstance的方法不断拿到新车,但是我们这个方法起码Car自己能够控制自己的诞生过程了,这就和“工厂”息息相关,我们设计工厂主要就是为了自主生产自己的产品,而不依赖new。比如要操控我的东西别人需要通过我提供的方法才能拿到而不是直接获取,这就是区别!!!因此我在getInsatnce方法内可以做各种各样的限制。因此,如果我从始至终就只想他开一辆车,下面就是完整的单例模式代码:
package com.TiHom.factory;

public class Car {
private static Car car;
4000

private Car(){}

public static Car getInstance(){  //instance的意思是实例对象,这里表示拿到实例对象
if(car != null){

}else {
car = new Car();
}
return car;
}

public void run(){
System.out.println("以200码的速度飞驰car......");
}
}

这里表示在getInstance的时候系统直接调用了已经定义好的car,这样的话你在同一个程序中无论怎么调用,最后都是调用的同一个Car对象。

1.2多例

package com.TiHom.factory;

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

public class Car {
private static Car car;
//多例
private static List<Car> cars = new ArrayList<Car>();

private Car(){}

public static Car getInstance(){  //instance的意思是实例对象,这里表示拿到实例对象
if(car != null){

}else {
car = new Car();
}
return car;
}

public static List<Car> getInstances(){
return cars;
}

public void run(){
System.out.println("以200码的速度飞驰car......");
}
}

JDBC的连接池中把连接创建在池里面,那个连接池就是多例的概念。

1.3静态工厂方法

其实只要有像getInstance一样在方法内产生了控制对象的逻辑,都可以称之为静态工厂方法,并不要局限于书上的条条框框。2.任意定制交通工具的类型和生产过程 —— 简单工厂方法

2.1实现任意定制交通工具

先实现一个Moveable接口package com.TiHom.factory;

public interface Moveable {
void run();
}然后让不同的交通工具类去实现接口即可
但是调用时要使用多态,即如下:package com.TiHom.factory;

public class Test {
public static void main(String[] args) {
// Car c = Car.getInstance();
// c.run();
Moveable m = new Plane();
m.run();
}
}



2.2任意定制生产过程

定义一个生产飞机的工厂
package com.TiHom.factory;

public class PlaneFactory {
public Plane createPlane(){
return new Plane();
}
}
测试类中
package com.TiHom.factory;

public class Test {
public static void main(String[] args) {
//        Car c = Car.getInstance();
//        c.run();
PlaneFactory pf = new PlaneFactory(); //***
Moveable m = pf.createPlane();
m.run();
}
}
可以用飞机工厂去创建飞机,并且在飞机工厂中可以自定义飞机的生产过程但是这还不完美,我们如果要开车而不是开飞机的话,我们需要把***语句整句话替换,所以继续改进使得想换工厂的话只换它的实现父类工厂:
package com.TiHom.factory;

/**
* 产生交通工具的工厂
*/
public abstract class VehicleFactory {
abstract Moveable create();
}
让飞机工厂和汽车工厂都去继承它


而现在要做改动只需改变一下new 的对象就行如:



改变后




简单工厂方法就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

这里还涉及到接口和抽象类使用场景的区别,下一篇文章进行简单区分。

3.系列产品(车、补给、武器....) —— 抽象工厂方法

3.1先创建系列产品





测试类
package com.TiHom.abstractfactory;

public class Test {
public static void main(String[] args) {
Car c = new Car();
c.run();
AWN awn = new AWN();
awn.shoot();
Hamburger h = new Hamburger();
h.eat();
}
}

3.2做到一系列产品替换掉就全给替换掉了

先创建一个默认工厂DefaultFactory
package com.TiHom.abstractfactory;

/**
* 默认人物就是手持AWN,嘴里吃着汉堡在开车
*/
public class DefaultFactory {
public Car createCar(){
return new Car();
}

public AWN createAWN(){
return new AWN();
}

public Hamburger createHamburger(){
return new Hamburger();
}
}
然后在测试类修改调用方法
package com.TiHom.abstractfactory;

public class Test {
public static void main(String[] args) {
DefaultFactory f = new DefaultFactory();
Car c = f.createCar();
c.run();
AWN awn = f.createAWN();
awn.shoot();
Hamburger h = f.createHamburger();
h.eat();
}
}

面向对象编程:好处是替换起来方便,扩展起来容易
下面是结构图:




当你想替换掉这一系列产品的时候,你只需要把这一系列产品造出来,对应的工厂造出来,同时换掉1、2类型的工厂就可以了。如果想把1这一系列的产品替换成2系列的产品,只需要换掉1工厂这个产生产品的地方就可以了
所以我们DefaultFactory和MagicFactory的接口必须统一起来


修改后最终测试类的调用做法是:
package com.TiHom.abstractfactory;

public class Test {
public static void main(String[] args) {
//如果现在想把DefaultFactory换成MagicFactory,需要把下面的方法全部改
AbstractFactory f = new MagicFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food food = f.createFood();
food.eat();
}
}
得到的结果是:




如果我们要改变输出的系列产品,只需要改一个地方:
//AbstractFactory f = new MagicFactory();
AbstractFactory f = new DefaultFactory();得到的结果就改变了:





如果你对这一系列产品都不满意,你只需添加你自己的系列产品,交通工具从Vehicle继承,食品从Food继承,武器从Weapon继承,然后产生自己的工厂,不用修改原来的代码,将来想换成自己的系列产品只需做上面测试类那样的改动即可。类似于网上那些换皮肤的软件。
[b]最后总结一下抽象工厂和它的实际应用场景:[/b]所谓抽象工厂就是它生产了一系列的产品,如果想换掉这一系列产品的时候或者是想在这一系列产品的基础上进行扩展,想产生新的系列产品,以及对这一系列产品的生产过程进行控制,就用抽象工厂。

抽象工厂和普通工厂的对比:

1.对于普通的工厂来说,我们是可以拓展产品的,可以产生新的产品和新的产品的工厂,但是如果要产生产品系列就会很麻烦了,如果要在普通工厂中产生产品系列就会造成工厂泛滥的结果。
2.对于抽象工厂来说,在产生新的产品品种上,比如我想让我上面定义的那个人再穿上防弹衣,而防弹衣由具体工厂产生,而这时候需要在工厂父类中动接口加上一个新的createXxx方法,然后所有原来实现过的子类都得加上新方法。
3.所以,这两者都有短处,就看实际如何运用。但是Spring提供了一种bean工厂方案把这两者的短处都进行了填补。

4.bean工厂(重点)

4.1.基于接口的类型任意定制(IOC)

暂时先不拓展,因为涉及到Spring 的内容,本人新手一枚还没学到

4.2.一定程度的生产过程定制(AOP)

5.使用工厂的实际开发场景:
1.Dao层操作数据库的时候使用,创建一个父类工厂BaseModel,它是所有框架model的基类。BaseModel其实就是数据库工厂,不同的模型去继承它,就有操作不同表数据表的对象实例了,这样就用一个基础的class完成了实例化各个不同数据表的对象,就好像工厂一样,传不同的表名就返回给你不同的的对象。
2.以后有新用法会不断拓展下去......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: