1.抽象工厂
1.图示:
工厂是抽象的,产品是抽象的,每个实际工厂负责创建一系列产品。
2. 示例代码:
假设我们希望为用户提供一个Markdown文本转换为HTML和Word的服务,它的接口定义如下:
- 抽象工厂
public interface AbstractFactory {
// 创建Html文档:
HtmlDocument createHtml(String md);
// 创建Word文档:
WordDocument createWord(String md);
}
- 抽象产品
两个抽象产品
// Html文档接口:
public interface HtmlDocument {
String toHtml();
void save(Path path) throws IOException;
}
// Word文档接口:
public interface WordDocument {
void save(Path path) throws IOException;
}
- 实际工厂
实际工厂1
public class FastFactory implements AbstractFactory {
@Override
public HtmlDocument createHtml(String md) {
return new FastHtmlDocument(md);
}
@Override
public WordDocument createWord(String md) {
return new FastWordDocument(md);
}
}
实际工厂2
public class GoodFactory implements AbstractFactory {
@Override
public HtmlDocument createHtml(String md) {
return new GoodHtmlDocument(md);
}
@Override
public WordDocument createWord(String md) {
return new GoodWordDocument(md);
}
}
- 实际工厂1 负责生产的实际产品,
产品A1
public class FastHtmlDocument implements HtmlDocument {
private String md;
public FastHtmlDocument(String md) {
this.md = md;
}
@Override
public String toHtml() {
return md.lines().map(s -> {
if (s.startsWith("#")) {
return "<h1>" + s.substring(1) + "</h1>";
}
return "<p>" + s + "</p>";
}).reduce("", (acc, s) -> acc + s + "\n");
}
@Override
public void save(Path path) throws IOException {
Files.write(path, toHtml().getBytes("UTF-8"));
}
}
产品B1
public class FastWordDocument implements WordDocument {
private String md;
public FastWordDocument(String md) {
this.md = md;
}
@Override
public void save(Path path) throws IOException {
String doc = "{\\rtf1\\ansi\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica-Bold;\\f1\\fswiss\\fcharset0 Helvetica;}\n";
String body = md.lines().map(s -> {
if (s.startsWith("#")) {
return String.format("\\f0\\b\\fs24 \\cf0%s\\par\n", s.substring(1));
}
return String.format("\\f1\\b0%s\\par\n", s);
}).reduce("", (acc, s) -> acc + s);
String content = doc + body + "}";
Files.write(path, content.getBytes("UTF-8"));
}
}
- 实际工厂2 负责生产的实际产品
产品A2
public class GoodHtmlDocument implements HtmlDocument {
private String md;
public GoodHtmlDocument(String md) {
this.md = md;
}
@Override
public String toHtml() {
//todo
}
@Override
public void save(Path path) throws IOException {
//todo
}
}
产品B2
public class GoodWordDocument implements HtmlDocument {
...
}
- 实际调用
public static void main(String[] args) throws IOException {
AbstractFactory fastFactory = new FastFactory();
HtmlDocument fastHtml = fastFactory.createHtml("#Hello\nHello, world!");
System.out.println(fastHtml.toHtml());
fastHtml.save(Paths.get(".", "fast.html"));
WordDocument fastWord = fastFactory.createWord("#Hello\nHello, world!");
fastWord.save(Paths.get(".", "fast.doc"));
AbstractFactory goodFactory = new GoodFactory();
HtmlDocument goodHtml = goodFactory.createHtml("#Hello\nHello, world!");
System.out.println(goodHtml.toHtml());
goodHtml.save(Paths.get(".", "good.html"));
WordDocument goodWord = goodFactory.createWord("#Hello\nHello, world!");
goodWord.save(Paths.get(".", "good.doc"));
}
2.工厂方法
先创建出某一具体工厂,再用工厂创建实现某一接口的具体产品。
1.图示:
2.代码示例
2.1 抽象产品:
Number 抽象产品
2.2 实际产品
BigDecimal 实际产品
2.2 工厂接口:
public interface NumberFactory {
Number parse(String s);
}
2.3 工厂实现类
public class NumberFactoryImpl implements NumberFactory {
public Number parse(String s) {
return new BigDecimal(s);
}
}
2.4 实际调用
NumberFactory factory = NumberFactory.getFactory();
Number result = factory.parse("123.456");
2.5 静态工厂方法
例如:Integer既是产品又是静态工厂。它提供了静态方法valueOf()来创建Integer。
代码示例:
不需要抽象工厂,通过工厂的静态方法直接返回产品。
public class LocalDateFactory {
private static Map<Integer, LocalDate> cache = new HashMap<>();
public static LocalDate fromInt(int yyyyMMdd) {
if (yyyyMMdd >= 20200101 && yyyyMMdd <= 20301231) {
LocalDate result = cache.get(yyyyMMdd);
if (result == null) {
result = create(yyyyMMdd);
cache.put(yyyyMMdd, result);
}
return result;
}
return create(yyyyMMdd);
}
private static LocalDate create(int yyyyMMdd) {
return LocalDate.of(yyyyMMdd / 10000, yyyyMMdd / 100 % 100, yyyyMMdd % 100);
}
}
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException {
LocalDate ld = LocalDateFactory.fromInt(20200202);
System.out.println(ld);
LocalDate ld2 = LocalDateFactory.fromInt(20200202);
System.out.println(ld == ld2);
}
}
3.简单工厂
一个工厂,根据不同的参数创建出实现产品接口某一具体产品。