简单工厂模式(Simple Factory Pattern)
生成复杂对象的地方,都可以考虑使用工厂模式。
角色
- 简单工厂
- 抽象产品
- 具体产品
uml
代码案例
产品接口
public interface FreshWaterFish {
void grow();//鱼生长
void harvest();//收获鱼
}
具体的产品
public class Carp implements FreshWaterFish{
@Override
public void grow() {
System.out.println("鲤鱼在生长");
}
@Override
public void harvest() {
System.out.println("捕获鲤鱼");
}
}
简单工厂
public class SingleProductFactory {
public static FreshWaterFish produceFish(String type){
if("草鱼".equals(type)){
return new GrassCarp();
}else if ("鲤鱼".equals(type)){
return new Carp();
}
System.out.println("抱歉,暂无此品种的鱼");
return null;
}
}
调用
public static void main(String[] args) {
FreshWaterFish GrassCrap = SingleProductFactory.produceFish("草鱼");
if(GrassCrap != null){
GrassCrap.grow();
GrassCrap.harvest();
}
FreshWaterFish Crap = SingleProductFactory.produceFish("鲤鱼");
assert Crap != null;
Crap.grow();
FreshWaterFish fish = SingleProductFactory.produceFish("黑鱼");
}
优点
- 具体的对象从客户这边代码解耦
- 服务端修改具体产品的类名,不影响使用
缺点
- 客户端要死记硬背,常量与产品的映射关系
- 如果具体产品特别多,在简单工厂中代码回很臃肿
3. 要扩展具体产品的时候要修改简单工厂的代码,违反了开闭原则
工厂模式(工厂方法模式)
角色
- 抽象工厂
- 具体工厂
- 抽象产品
- 具体产品
uml
代码案例
抽象的产品,也可以是接口
public abstract class Laptop {
private String brand;//品牌
public Laptop(String brand) {
this.brand = brand;
}
abstract public String getId();
public void getDescription(){
System.out.println("this is a " + brand +"Laptop");
}
}
具体产品类
public class LenovoLaptop extends Laptop {
private static final String brand = "LENOVO";
protected static int initId;
public LenovoLaptop() {
super(LenovoLaptop.brand);
initId = 200;
}
@Override
public String getId() {
return "LENOVO--"+(initId++);
}
}
抽象的工厂
public interface LaptopFactory {
Laptop produce();//生产笔记本电脑
void afterSaleService();//售后服务
}
具体工厂
public class LenovoFactory implements LaptopFactory {
@Override
public Laptop produce() {
return new LenovoLaptop();
}
@Override
public void afterSaleService() {
System.out.println("欢迎到来联想服务售后热线");
}
}
调用
public static void main(String[] args) {
LaptopFactory f1 = new LenovoFactory();
Laptop produce = f1.produce();
f1.afterSaleService();
produce.getDescription();
System.out.println(produce.getId());
}
优点
- 依然具有简单工厂模式的优点,服务端修改具体的类名,客户端可以不用知道
- 当产品要扩展一个新类的时候不用修改原来的代码(**ps:**可以用简单工厂模式包装工厂模式)
疑点
- 当我们使用工厂方法的时候,客户端不是依赖与具体的工厂吗,如果服务端修改工厂名,客户端也要修改?
- 工厂的名字,是视为接口的。作为作者有责任保正工厂的名字是稳定的。
缺点
- 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性
抽象工厂模式
名词解释
- **产品等级:**实现产品接口所创建的所有产品(产品的继承结构)。
- **产品族:**一个工厂生产的一系列产品。
角色
- 抽象工厂
- 具体工厂
- 抽象产品
- 具体产品
uml
代码案例
抽象产品类
public abstract class Laptop {
private String brand;
public Laptop(String brand) {
this.brand = brand;
}
abstract public String getId();
public void getDescription(){
System.out.println("this is a"+ brand+"Laptop");
}
}
public abstract class MobilePhone {
abstract void activate();
}
产品
public class AcerLaptop extends Laptop{
private static final String brand ="ACER";
private static int initId;
public AcerLaptop() {
super(brand);
initId = 100;
}
@Override
public String getId() {
return "ACER--"+(initId++);
}
}
public class AcerPhone extends MobilePhone{
@Override
void activate() {
System.out.println("宏基手机被激活");
}
}
抽象工厂
public interface AbstractFactory {
MobilePhone getMobilePhone();
Laptop getLaptop();
}
工厂
public class AcerFactory implements AbstractFactory {
@Override
public MobilePhone getMobilePhone() {
return new AcerPhone();
}
@Override
public Laptop getLaptop() {
return new AcerLaptop();
}
}
优点
- 任有简单工厂和工厂方法的优点
- 把抽象工厂减少了,无论有多少产品等级,抽象工厂只有一套
缺点
- 当产品等级发生变化时,以前的产品的工厂代码也要修改。违反开闭原则