历览前贤国与家,成由勤俭破由奢。
何须琥珀方为枕,岂得真珠始是车。
运去不逢青海马,力穷难拔蜀山蛇。
几人曾预南薰曲,终古苍梧哭翠华。
——《咏史二首·其二》李商隐
听网络课程后的笔记,还不是很理解,小弟先记下,待未来小有理解后再来完善。
一、工厂方法
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。工厂方法的就是定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟。
根据分析图可以看到工厂方法必须先要有产品与产品工厂的接口,再由我们去实习接口,继承同一个接口的不同产品每个产品都应该有一个工厂类。
interface Product {
}
interface Factory {
Product createProduct();
}
public class Client {
public static void main(String[] args) {
FactoryA fa = new FactoryA();
FactoryB fb = new FactoryB();
Product a = fa.createProduct();
Product b = fb.createProduct();
}
}
class ProductA implements Product {
ProductA() {
System.out.println("这是产品A,由A工厂创建");
}
}
class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
class ProductB implements Product {
ProductB() {
System.out.println("这是产品B,由B工厂创建");
}
}
class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
总结
- 工厂方法模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合(new)会导致软件脆弱。
- 工厂方法模式通过面向对象的手法,将所要创建的具体类型工作延迟到子类,从而实现一种扩展而非更改的策略,较好地解决了这种紧耦合关系。
- 工厂方法模式解决单个对象的需求变化。缺点在于要求创建方法/参数相同。
由此可知当我们要创建一些外壳相同(创建方法/参数相同),内部需求变化的对象,就可以是用工厂方法。记住每一个具体对象要有一个工厂类。
二、抽象工厂模式
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在更多系列对象的创建工作。
与工厂方法模式不同的是,抽象工厂适合于“一系列相互依赖的对象”,而工厂不只是生产单一产品,而是从零件到完成品一条龙生产。小弟做了个肉串工厂(羊肉串,牛肉串),嘻嘻
public class Client {
public static void main(String[] args) {
KebabFactory factory1 = new MuttonKebabFactory();
Meat mutton = factory1.purchaseMeat("顶级");
Seasoning muttonSeasoning = factory1.makeSeasoning("微辣");
Kebab muttonKebab = factory1.produceKebab(mutton, muttonSeasoning);
System.out.println(muttonKebab.getKebabInfo());
//
KebabFactory factory2 = new BeefKebabFactory();
Meat beef = factory2.purchaseMeat("五星");
Seasoning beefSeasoning = factory2.makeSeasoning("黑椒");
Kebab beefKebab = factory2.produceKebab(beef, beefSeasoning);
System.out.println(beefKebab.getKebabInfo());
}
}
//肉的基类
abstract class Meat {
abstract String getLevel();
}
//特制调料的基类
abstract class Seasoning {
abstract String getFlavor();
}
//肉串基类
abstract class Kebab {
abstract String getKebabInfo();
}
/**
* 抽象肉串工厂类
*/
abstract class KebabFactory {
public abstract Meat purchaseMeat(String level);
public abstract Seasoning makeSeasoning(String flavor);
public abstract Kebab produceKebab(Meat meat, Seasoning seasoning);
}
//羊肉类
class Mutton extends Meat {
private String level;
Mutton(String level) {
this.level = level;
}
@Override
public String getLevel() {
return level;
}
}
//特制羊肉调料
class MuttonSeasoning extends Seasoning {
private String flavor;
MuttonSeasoning(String flavor) {
this.flavor = flavor;
}
@Override
public String getFlavor() {
return flavor;
}
}
//羊肉串类
class MuttonKebab extends Kebab {
private Meat meat;
private Seasoning seasoning;
MuttonKebab(Meat meat, Seasoning seasoning) {
this.meat = meat;
this.seasoning = seasoning;
}
@Override
public String getKebabInfo() {
return meat.getLevel() + seasoning.getFlavor() + "羊肉串";
}
}
/**
* 羊肉串加工厂
* (具体工厂类)
*/
class MuttonKebabFactory extends KebabFactory {
@Override
public Meat purchaseMeat(String level) {
return new Mutton(level);
}
@Override
public Seasoning makeSeasoning(String flavor) {
return new MuttonSeasoning(flavor);
}
@Override
public Kebab produceKebab(Meat meat, Seasoning seasoning) {
return new MuttonKebab(meat, seasoning);
}
}
//牛肉类
class Beef extends Meat {
private String level;
Beef(String level) {
this.level = level;
}
@Override
public String getLevel() {
return level;
}
}
//特制牛肉调料类
class BeefSeasoning extends Seasoning {
private String flavor;
BeefSeasoning(String flavor) {
this.flavor = flavor;
}
@Override
public String getFlavor() {
return flavor;
}
}
//牛肉串类
class BeefKebab extends Kebab {
private Meat meat;
private Seasoning seasoning;
BeefKebab(Meat meat, Seasoning seasoning) {
this.meat = meat;
this.seasoning = seasoning;
}
@Override
public String getKebabInfo() {
return meat.getLevel() + seasoning.getFlavor() + "牛肉串";
}
}
/**
* 牛肉串加工厂
* (具体工厂类)
*/
class BeefKebabFactory extends KebabFactory {
@Override
public Meat purchaseMeat(String level) {
return new Beef(level);
}
@Override
public Seasoning makeSeasoning(String flavor) {
return new BeefSeasoning(flavor);
}
@Override
public Kebab produceKebab(Meat meat, Seasoning seasoning) {
return new BeefKebab(meat, seasoning);
}
}
按照分析图走,我首先创建了产品(肉,调料,肉串)和工厂的接口,由于不同的需求(牛肉串、羊肉串),又分别创建了各自的具体类与具体工厂类,而肉串最终是由肉和调料一起加工而成,加工过程都是在工厂中完成,一条龙服务呀。
总结
- 如果没有应对“多系列对象构建”的需求变化,则没有必要使用抽象工厂模式,这时候使用简单工厂就行
- “系列对象”指的是在某一特定系列下的对象之间相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
- 抽象工厂模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变化。