前言
以前學(xué)習(xí)設(shè)計(jì)模式的時(shí)候, 通常都是咖啡館, 披薩店, 各種各樣的紅綠頭鴨. 明顯地, 這些概念需要更新一下, 這次我們用MacBook和XPS13兩臺(tái)電腦作為例子來(lái)快速?gòu)?fù)習(xí)創(chuàng)建型設(shè)計(jì)模式.
創(chuàng)建型模型簡(jiǎn)單直接, 所以大部分模式直接通過(guò)UML進(jìn)行展示, 個(gè)別需要特別注意的將會(huì)以代碼的形式展示.
完整代碼已上傳至GitOSC
簡(jiǎn)單工廠
簡(jiǎn)單工廠可以為客戶端選擇具體的實(shí)現(xiàn)
下面是LaptopFactory生產(chǎn)MacBook和Xps13的例子
UML
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
// 生成rmbp
final MacBook implA = LaptopFactory.createMacBook();
implA.doSomething();
// 生產(chǎn)xps
final Xps13 implB = LaptopFactory.createXps13();
implB.doSomething();
}
}
工廠方法模式 - Factory method
與簡(jiǎn)單工廠的區(qū)別在于工廠方法模式允許將類的實(shí)例化推遲到子類中, 如果把工廠方法中的具體實(shí)現(xiàn)放到父類中, 那么就等同于簡(jiǎn)單工廠
下面是LaptopFactory將生產(chǎn)Laptop的功能分別推遲至AppleFactory
和DellFactory
的例子
UML
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final LaptopFactory laptopFactory = new AppleFactory();
laptopFactory.someWork();
}
}
小結(jié)
工廠父類是一個(gè)抽象類, 里面有個(gè)protected abstract方法就是工廠方法
一般工廠方法返回的是被創(chuàng)建對(duì)象的接口對(duì)象, 當(dāng)然也可以是抽象類或者一個(gè)具體的類的實(shí)例
工廠方法可以看成一個(gè)生成對(duì)象的抽象方法
抽象工廠模式 - Abstract factory
創(chuàng)建一系列的產(chǎn)品對(duì)象, 而且這一系列對(duì)象是構(gòu)建新的對(duì)象所需要的組成部分, 簡(jiǎn)而言之就是這一系列被創(chuàng)建的對(duì)象相互之間是有約束的.
如今不僅需要生產(chǎn)電腦, 還要生產(chǎn)電源適配器, 這兩個(gè)組成了產(chǎn)品簇. 顯而易見的是XPS不能使用MacBook的電源.
UML
Client Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final LaptopFactory factory = new AppleFactory();
factory.createLaptop();
factory.createPowerAdaptor();
}
}
原型模式 - Prototype
<u>可忽略</u>, 在實(shí)際工作中更多地會(huì)使用第三方類庫(kù)完成深拷貝
下面是克隆MacBook的例子
UML
Usage
/**
* @author Zhao Junjian
*/
public class PrototypeTester {
@Test
public void testClone() throws Exception {
// 你就只管我們生成一個(gè)List對(duì)象就行
final List<MacBook.Cpu> cpuList = new ArrayList<>();
for (int i = 1; i <= 4; i++) {
final MacBook.Cpu cpu = new MacBook.Cpu(i);
cpuList.add(cpu);
}
final MacBook macBook = new MacBook();
macBook.setCpuArray(cpuList.toArray(new MacBook.Cpu[cpuList.size()]));
macBook.setCpuList(cpuList);
macBook.setKeyboard(87);
macBook.setMemory("16G");
// 全部準(zhǔn)備完成, 我們就開始克隆一個(gè)新的實(shí)體
final MacBook newMacBook = macBook.clone();
Assert.assertEquals(macBook, newMacBook);
// 修改引用類型
final MacBook.Cpu newCpu = new MacBook.Cpu(5);
cpuList.add(newCpu);
newMacBook.setCpuList(cpuList);
// 如果這里拋出異常, 就證明是淺拷貝. 實(shí)際情況就是淺拷貝.
Assert.assertNotEquals(macBook, newMacBook);
}
}
小結(jié)
MacBook
需要實(shí)現(xiàn)標(biāo)識(shí)接口Cloneable, 并在clone()
方法里面顯式地調(diào)用父類的clone()
@Override
protected MacBook clone() throws CloneNotSupportedException {
return (MacBook) super.clone();
}
單例模式 - Singleton
這里著重于講解懶漢式, 因?yàn)橛行枰⒁獾募?xì)節(jié), 所以直接貼代碼.
實(shí)現(xiàn)單例有3種模式, 嵌套類, 雙重檢查和枚舉
嵌套類 holder
/**
* @author Zhao Junjian
*/
public class DellFactory {
private DellFactory() {
System.out.println("dell is the best");
}
private static final class DellFactoryHolder {
private static final DellFactory FACTORY = new DellFactory();
}
public static DellFactory getInstance() {
return DellFactoryHolder.FACTORY;
}
}
雙重檢查 double-checked
/**
* @author Zhao Junjian
*/
public class AppleFactory {
private static volatile AppleFactory FACTORY;
public static AppleFactory getInstance() {
if (FACTORY == null) {
//Client.LATCH.await();
synchronized (AppleFactory.class) {
if (FACTORY == null) {
FACTORY = new AppleFactory();
}
}
}
return FACTORY;
}
private AppleFactory() {
System.out.println(Thread.currentThread().getName() + " wanna get a hurt");
}
}
枚舉 enum
/**
* @author Zhao Junjian
*/
public enum RazerFactory {
STEALTH;
public void doSomething() {
// ...
}
}
建造者模式/生成器模式 - Builder
實(shí)際中有兩種方法可以快速構(gòu)建Fluent API, 第一是安裝插件, 第二是使用Lombok
被構(gòu)建者的私有構(gòu)造器, 公開靜態(tài)的builder()方法
下面是通過(guò)建造者生成MacBook的例子
/**
* @author Zhao Junjian
*/
@Data
public class MacBook {
private String processor;
private int memory;
private long capacity;
private String keyboard;
private MacBook(Builder builder) {
processor = builder.processor;
memory = builder.memory;
capacity = builder.capacity;
keyboard = builder.keyboard;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private String processor;
private int memory;
private long capacity;
private String keyboard;
public Builder processor(String val) {
processor = val;
return this;
}
public Builder memory(int val) {
memory = val;
return this;
}
public Builder capacity(long val) {
capacity = val;
return this;
}
public Builder keyboard(String val) {
keyboard = val;
return this;
}
public MacBook build() {
return new MacBook(this);
}
}
}
Usage
/**
* @author Zhao Junjian
*/
public class Client {
public static void main(String[] args) {
final MacBook macBook = MacBook.builder().processor("core").memory(9481).capacity(102931L).build();
}
}
作者:Chris
原博客:http://blog.chriscs.com