简单工厂模式

引自 spring温故知新对几种设计模式讲解比较清晰

 

1:传统的编程方式


public class Robot {
public String name;
public String color;
public double height;
public double width;
public double weight;
public Robot(String name, String color, double height, double width,
double weight) {
this.name = name;
this.color = color;
this.height = height;
this.width = width;
this.weight = weight;
}
public void Speak(String msg) {
System.out.println(msg);
}
}

实现类

 

import com.iteye.bolide74.action.Robot;
public class IoCTester {
public static void main(String[] args) {
Robot robot0 = new Robot("robot0", "black", 80.000, 40.0000, 1000.0000);
robot0.Speak("Hello,World!");
}
}

 

2: 使用简单工厂

 

import com.iteye.bolide74.action.Robot;
class RobotFactory {
public Robot getRobot(int robotType) {
Robot robot;
switch (robotType) {
case 0:
robot = new Robot("robot0", "black", 80.000, 40.0000, 1000.0000);
break;
case 1:
robot = new Robot("robot1", "white", 90.000, 30.0000, 800.0000);
break;
default:
robot = new Robot("defaultRobot", "red", 10.000, 10.0000, 300.0000);
break;
}
return robot;
}
}
public class IoCTester {
public static void main(String[] args) {
RobotFactory robotFactory = new RobotFactory();
Robot robot = robotFactory.getRobot(0);
robot.Speak("Hello,World! My name is " + robot.name);

}

}

 

3:使用静态工厂

 

package com.iteye.bolide74.action;
public class Robot2 {
public String name;
public String color;
public double height;
public double width;
public double weight;


private Robot2(String name, String color, double height, double width,
double weight) {
this.name = name;
this.color = color;
this.height = height;
this.width = width;
this.weight = weight;
}


public static Robot2 getRobot(int robotType) {
Robot2 robot2;
switch (robotType) {
case 0:
robot2 = new Robot2("robot0", "black", 80.000, 40.0000, 1000.0000);
break;
case 1:
robot2 = new Robot2("robot1", "white", 90.000, 30.0000, 800.0000);
break;
default:
robot2 = new Robot2("defaultRobot", "red", 10.000, 10.0000, 300.0000);
break;
}
return robot2;
}
public void Speak(String msg) {
System.out.println(msg + ",我是" + this.name);
}
}


实现类
package com.iteye.bolide74.tester;
import com.iteye.bolide74.action.Robot2;
public class IoCTester {
public static void main(String[] args) {
Robot2 robot2 = Robot2.getRobot(1);
robot2.Speak("Hello,world!");

 

注意!这里有两个细节:
1) Robot2的构造方法是private的,这样的好处就是所有Robot2的使用者或者说是实现类在获取机器人的时
候,只能通过getRobot2来获取,这样就实现了规范化,而不是有些地方是直接new的,有些地方是用
getRobot方法来的(一个项目,不一定就是一个程序员写到老的...)。
2) Robot2获取实例的getRobot方法是static静态的(所以才叫静态工厂嘛~)!由于Robot2的构造函数是
private的了,不能直接new一个实例,那就更加不可能调用需要实例化才能使用的getRobot方法了,所以必须
要设置为static方法,就可以无需实例化直接调用!

 

 

现在为了解决简单工厂和静态工厂模式的缺陷,我们可以把Speak这个方法(或者可以称为功能模块)抽取出
来,作为一个接口来实现,这样只要People类和Robot类都实现这个接口,就能够通用了。
package com.iteye.bolide74.impl;
public interface ISpeaker {
public void Speak(String msg);
}

接下来是新的Robot类和People类,它们都同时实现了ISpeaker这个接口,两者都用了不同的Speak内容来区
分人类和机器人说话方式的不同:
package com.iteye.bolide74.action;
import com.iteye.bolide74.impl.ISpeaker;
public class Robot implements ISpeaker {
public String name;
public String color;
public double height;
public double width;
public double weight;
public Robot(String name, String color, double height, double width,
double weight) {
this.name = name;
this.color = color;
this.height = height;
this.width = width;
this.weight = weight;
}
@Override
public void Speak(String msg) {
System.out.println(msg + ",我是" + this.name + ",我的体重为" + this.weight);
}
}
package com.iteye.bolide74.action;
import com.iteye.bolide74.impl.ISpeaker;
public class People implements ISpeaker {
public String name;
public double height;
public double weight;:

public People(String name, double height, double weight) {
this.name = name;
this.height = height;
this.weight = weight;
}
@Override
public void Speak(String msg) {
System.out.println(msg + ",我是" + this.name + ",我就不告诉你我有多重!");
}
}
接下来就是工厂类和实现类了。这个工厂类就不是生产具体的实例对象了,而是生产一个通用的能够Speak的抽
象实例(某个能打招呼的东西,或许是人类,或许是机器人)
package com.iteye.bolide74.tester;
import com.iteye.bolide74.action.People;
import com.iteye.bolide74.action.Robot;
import com.iteye.bolide74.impl.ISpeaker;
class SpeakerFactory {
public ISpeaker getSpeaker(int speakerType) {
ISpeaker speaker;
switch (speakerType) {
case 0:
speaker = new Robot("robot0", "black", 80.000, 40.0000, 1000.0000);
break;
case 1:
speaker = new People("GirlFriend", 1.64, 99.99);
break;
default:
speaker = new Robot("defaultRobot", "red", 10.000, 10.0000,
300.0000);
break;

}
return speaker;
}
}
public class IoCTester {
public static void main(String[] args) {
SpeakerFactory speakerFactory = new SpeakerFactory();
ISpeaker speaker = speakerFactory.getSpeaker(1);
speaker.Speak("Hello,World!");
}
}
输出结果:
引用
Hello,World!,我是GirlFriend,我就不告诉你我有多重!
如此一来的话就很方便了,我们不用再像之前的简单工厂模式那样每次打招呼的时候都要重新实例化一个不同
的工厂,而是实例化了一个能生成某种类别不确定但是一定能够speak打招呼的对象的通用工厂,然后用统一
ISpeaker接口来实例化“打招呼”这个功能模块,至于打招呼是让机器人去还是让女朋友去就只要抽象工厂生
成的时候告诉它一下代号就行了。
这样的话就能够在尽可能少修改实现代码的前提下,尽可能的实现各种情况下的同一种功能。

4:单例模式

 

 

package com.iteye.bolide74.action;
public class Girlfriend {
private static Girlfriend girlfriend; //类的静态成员属性形式声明一个实例
public String name;
public double height;
public double weight;
private Girlfriend(String name, double height, double weight) {
this.name = name;
this.height = height;
this.weight = weight;
}
public static Girlfriend getGirlfriend() {
if (girlfriend == null)
girlfriend = new Girlfriend("GirlFriend", 1.64, 99.99);
return girlfriend;
}
public void Speak(String msg) {
System.out.println(msg + ",我是" + this.name + ",我是唯一的女朋友");
}
}
大家可以看到这个Girlfriend类,跟前面一篇的静态工厂模式非常像,它们的构造函数都是private私有的,都有
一个静态的实例生成方法。作用也是相同的,就是限制生成实例的办法只有一种,就是通过getGirlfriend()方法
来获取。
区别有两点:
1) 静态工厂生成的实例对象{Robot2 robot2;},都是在getRobot()这个生产实例的方法内部声明的,也就是说
这些引用对象都是局部变量。
而单例模式里生成的实例对象{private static Girlfriend girlfriend;},是在getGirlfriend()这个生产实例的方
法的外部声明,并且还加了static静态修饰词的,这就代表了它这个是类的静态成员属性,它是唯一的并且是无
需实例化就能使用的(因为是static的),只不过这里又加了一个private私有修饰词,不能被外部直接访问而已。
2) Girlfriend类里的getGirlfriend()方法内部,加了一个判断,作用是如果girlfriend这个静态类属性,同时也是
这个类的一个实例对象为null,那么就新建一个实例对象给它;如果不为null,也就是已经有实例了,那么就直
接返回已经存在的那个实例对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值