一、定義
建造者模式伊脓,將一個復(fù)雜的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示串纺。
二丽旅、模板方法模式結(jié)構(gòu)圖
建造者
角色 | 類別 | 說明 |
---|---|---|
Builder | 接口或抽象類 | 抽象的建造者,不是必須的 |
ConcreateBuilder | 具體的建造者 | 可以有多個「因為每個建造風(fēng)格可能不一樣」 |
Product | 普通的類 | 具體的產(chǎn)品「即被建造的對象」 |
Director | 導(dǎo)演也叫指揮者 | 統(tǒng)一指揮建造者去建造目標(biāo)纺棺,導(dǎo)演不是必須的 |
三榄笙、模式的實現(xiàn)
public class Product {
private List<String> parts = new ArrayList<>();
public void addPart(String part) {
parts.add(part);
}
public void showProduct() {
for (String part : parts) {
System.out.println(part);
}
}
}
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getResult();
}
public class ConcreteBuilderOne extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.addPart("部件A");
}
@Override
public void buildPartB() {
product.addPart("部件B");
}
@Override
public Product getResult() {
return product;
}
}
public class ConcreteBuilderTwo extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.addPart("部件A");
}
@Override
public void buildPartB() {
product.addPart("部件B");
}
@Override
public Product getResult() {
return product;
}
}
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
public static void main(String[] args) {
Director director = new Director();
Builder builderOne = new ConcreteBuilderOne();
Builder builderTwo = new ConcreteBuilderTwo();
director.construct(builderOne);
Product p1 = builderOne.getResult();
p1.showProduct();
director.construct(builderTwo);
Product p2 = builderTwo.getResult();
p2.showProduct();
}
四、使用的案例
dubbo 源碼中獲取內(nèi)存cache的一段邏輯就是用了建造者模式祷蝌,接著直接貼上源碼對照著上面的四部分茅撞。
分析:構(gòu)建cache都要先緩存到一個map中去,get的時候先從map獲取巨朦,獲取不到米丘,在構(gòu)建,然后放入map糊啡。整個流程是固定的拄查,只是放入的Cache有多種。
Product
public interface Cache {
void put(Object key, Object value);
Object get(Object key);
}
public class LruCache implements Cache {
private final Map<Object, Object> store;
public LruCache(String url) {
final int max = 1000;
//TODO 1 LinkedHashMap可以做成lru格式的
this.store = new LinkedHashMap<Object, Object>() {
private static final long serialVersionUID = -3834209229668463829L;
@Override
protected boolean removeEldestEntry(Entry<Object, Object> eldest) {
return size() > max;
}
};
}
@Override
public void put(Object key, Object value) {
synchronized (store) {
store.put(key, value);
}
}
@Override
public Object get(Object key) {
synchronized (store) {
return store.get(key);
}
}
}
Builder
public abstract class AbstractCacheFactory implements CacheFactory {
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
@Override
public Cache getCache(String url) {
String key = url;
Cache cache = caches.get(key);
if (cache == null) {
caches.put(key, createCache(url));
cache = caches.get(key);
}
return cache;
}
protected abstract Cache createCache(String url);
}
ConcreteBuliderOne
public class LruCacheFactory extends AbstractCacheFactory {
@Override
protected Cache createCache(String url) {
return new LruCache(url);
}
}
ConcreteBuliderTwo
public class JCacheFactory extends AbstractCacheFactory {
protected Cache createCache(URL url) {
return new JCache(url);
}
}
Director
public class Director {
public Cache construct(AbstractCacheFactory abstractCacheFactory) {
return abstractCacheFactory.getCache("cache");
}
}
public class Director {
public Cache construct(AbstractCacheFactory abstractCacheFactory) {
return abstractCacheFactory.getCache("cache");
}
}
public static void main(String[] args) {
Director director = new Director();
AbstractCacheFactory abstractCacheFactory = new LruCacheFactory();
Cache cache = director.construct(abstractCacheFactory);
}
四棚蓄、建造者模式的特點
1堕扶、使創(chuàng)建產(chǎn)品的步驟「把創(chuàng)建產(chǎn)品步驟放在不同的方法中,更加清晰直觀」和產(chǎn)品本身分離梭依,即使用相同的創(chuàng)建過程要吧創(chuàng)建出不同的產(chǎn)品
2稍算、每個建造者都是獨立的互不影響,這樣就達到解耦的目的役拴,所以如果想要替換現(xiàn)有的建造者那非常方便糊探,添加一個實現(xiàn)即可。
所以說河闰,建造者模式實在創(chuàng)建復(fù)雜對象的算法應(yīng)該獨立于該對象的組成部分以及它們的裝配方式是使用的模式科平。