本文代码较多且综合了好几种设计模式使用,建议收藏或者慢慢观看。

本文将综合抽象工厂、组合模式、装饰器模式、适配器模式、观察者模式等模式运用在本例子中。对于不熟悉这些模式的读者可以阅读历史文章学习加强自己的代码心法。完整代码在 github:https://github.com/UniqueDong/zero-design-patterns 对应的 com.zero.headfirst.verb 包目录下。

适配器模式

首先我们从制造一个屏幕模拟器开始,模拟鸭子叫,根据需求我们先定义 Quackable接口,然后分别定义MallarDuck、RedheadDuck、RubberDuck、DuckCall等不同的鸭子实现呱呱叫接口,这个时候有鸭子出现的地方也出现了鹅混在其中,我们就通过适配器模式适配成鸭子。

/*** 鸭子呱呱叫接口*/
public interface Quackable {/*** 呱呱叫*/void quack();
}/*** 鸭子叫玩具*/
public class DuckCall implements Quackable {@Overridepublic void quack() {System.out.println("鸭子模拟器叫...");}
}public class MallarDuck implements Quackable {@Overridepublic void quack() {System.out.println("标准绿头鸭呱呱叫...");}
}public class RedheadDuck implements Quackable {@Overridepublic void quack() {System.out.println("红头鸭呱呱叫...");}
}public class RubberDuck implements Quackable {@Overridepublic void quack() {System.out.println("橡皮鸭吱吱叫...");}
}

现在各种鸭子定义好了,我们定义鹅 Goose

/*** 天鹅,假装鸭子在模拟器中出现*/
public class Goose {public void honk() {System.out.println("天鹅叫声,额");}
}

这个时候需要适配器将鹅适配成鸭子,适配器持有鹅的引用,鹅就是被适配对象,同时适配器实现 Quackable接口,当调用 quack()的时候实际是委托调用了honk()方法。

/*** 将天鹅适配成鸭子*/
public class GooseAdapter implements Quackable {/*** 持有被修饰的对象*/private Goose goose;public GooseAdapter(Goose goose) {this.goose = goose;}@Overridepublic void quack() {goose.honk();}
}

最后我们的屏幕模拟器登场,展示满屏呱呱叫的鸭子与鹅。

public class DuckSimulation {public static void main(String[] args) {DuckSimulation simulation = new DuckSimulation();simulation.simulate();}/*** 模拟屏幕展示功能*/private void simulate() {Quackable redheadDuck = new RedheadDuck();Quackable mallarDuck = new MallarDuck();Quackable rubberDuck = new RubberDuck();Quackable duckCall = new DuckCall();GooseAdapter gooseAdapter = new GooseAdapter(new Goose());simulate(redheadDuck);simulate(mallarDuck);simulate(rubberDuck);simulate(duckCall);simulate(gooseAdapter);}private void simulate(Quackable quackable) {quackable.quack();}}

装饰器-统计鸭子叫的次数

现在继续新增需求,在鸭子类不修改的情况下我们要统计叫的次数。我们创建一个装饰者,通过把鸭子包装进装饰者对象,然后给鸭子新的功能(计算叫的次数)。装饰器也要实现 Quackable接口,并且持有鸭子实例变量-被装饰者,内部使用一个静态变量保存叫的次数,当 quack()被调用的时候我们就把调用委托给被装饰的 Quackable对象,并且把叫的次数加 1。

/*** 装饰器模式,发出叫声的时候同时记录次数.这样我们就不必修改每个鸭子发出声音的方法*/
public class QuackCounter implements Quackable {private Quackable quack;private static AtomicInteger atomicInteger = new AtomicInteger(0);public QuackCounter(Quackable quack) {this.quack = quack;}@Overridepublic void quack() {quack.quack();atomicInteger.incrementAndGet();}public static AtomicInteger getQuacks() {return atomicInteger;}
}

利用装饰器模式-我们实现了不修改鸭子类却又给鸭子新增了功能。接着我们需要修改屏幕模拟器,将需要统计叫声的鸭子包装在装饰器中。

public class DuckSimulation {public static void main(String[] args) {DuckSimulation simulation = new DuckSimulation();simulation.simulate();}/*** 模拟屏幕展示功能*/private void simulate() {// 使用装饰器包装鸭子Quackable redheadDuck = new QuackCounter(new RedheadDuck());Quackable mallarDuck = new QuackCounter(new MallarDuck());Quackable rubberDuck = new QuackCounter(new RubberDuck());Quackable duckCall = new QuackCounter(new DuckCall());//不想把天鹅的叫声统计,所以不用装饰器装饰天鹅GooseAdapter gooseAdapter = new GooseAdapter(new Goose());System.out.println("使用装饰器模式后,统计叫的次数,不包含天鹅");simulate(redheadDuck);simulate(mallarDuck);simulate(rubberDuck);simulate(duckCall);simulate(gooseAdapter);System.out.println("一共叫了 "   QuackCounter.getQuacks()   " 次");}private void simulate(Quackable quackable) {quackable.quack();}}

抽象工厂

写到这里我们已经用上了适配器模式、装饰器模式。有没有觉得我们创建鸭子都是 new 出来的?为什么不把创建鸭子的的程序集合集中在一个地方,换句话说就是将创建于修饰的部分包装起来。就是我们接下来要说的:工厂模式。

我们定义一个工厂,生产各种不同类型的鸭子产品家族,所以我们使用抽象工厂模式。

首先从定义抽象工厂 AbstractDuckFactory开始,用于创建不同类型的鸭子家族。

/*** 抽象工厂模式,定义产品族*/
public abstract class AbstractDuckFactory {public abstract Quackable createDuckCall();public abstract Quackable createMallarDuck();public abstract Quackable createRedheadDuck();public abstract Quackable createRubberDuck();
}

接着创建一个普通鸭子工厂继承抽象工厂,该工厂创建没有装饰器装饰的鸭子。屏幕模拟器并不知道实际的产品是什么,只知道它实现了 Quackable接口。把创建细节丢给工厂,而不是直接 new 创建,这也是控制反转的思想,在 Spring 框架中大量出现。

/*** 每个方法创建一种产品,一种特定种类的 Quackable*/
public class DuckFactory extends AbstractDuckFactory {@Overridepublic Quackable createDuckCall() {return new DuckCall();}@Overridepublic Quackable createMallarDuck() {return new MallarDuck();}@Overridepublic Quackable createRedheadDuck() {return new RedheadDuck();}@Overridepublic Quackable createRubberDuck() {return new RubberDuck();}
}

现在我们要创建带计数器叫声功能的鸭子工厂DuckCountFactory,它持有DuckFactory 的一个实例用于创建普通鸭子并放进 QuackCounter装饰器中从而得以创建带计数器的鸭子。这里其实也是用到了装饰器模式。

/*** 叫声计数器工厂:同时还结合了装饰器模式,持有 工厂引用,包装了duckFactory,从而增强了功能* 创建计数器鸭子*/
public class DuckCountFactory extends AbstractDuckFactory {private AbstractDuckFactory duckFactory;public DuckCountFactory(DuckFactory duckFactory) {this.duckFactory = duckFactory;}@Overridepublic Quackable createDuckCall() {return new QuackCounter(duckFactory.createDuckCall());}@Overridepublic Quackable createMallarDuck() {return new QuackCounter(duckFactory.createMallarDuck());}@Overridepublic Quackable createRedheadDuck() {return new QuackCounter(duckFactory.createRedheadDuck());}@Overridepublic Quackable createRubberDuck() {return new QuackCounter(duckFactory.createRubberDuck());}
}

既然工厂我们定义好了,接下来就要修改屏幕模拟器代码运用工厂来产生鸭子。我们创建一个多态方法simulate(),此方法需要一个用来创建对象的工厂,传入不同的工厂则生产不同的产品家族。

我们把原来直接 new 产生鸭子的代码改造成通过工厂创建,代码如下。

public class DuckSimulation {public static void main(String[] args) {DuckSimulation simulation = new DuckSimulation();AbstractDuckFactory duckCountFactory = new DuckCountFactory(new DuckFactory());simulation.simulate(duckCountFactory);}/*** 模拟屏幕展示功能*/private void simulate(AbstractDuckFactory duckFactory) {Quackable redheadDuck = duckFactory.createRedheadDuck();Quackable mallarDuck = duckFactory.createMallarDuck();Quackable rubberDuck = duckFactory.createRubberDuck();Quackable duckCall = duckFactory.createDuckCall();//不想把天鹅的叫声统计,所以不用装饰器装饰GooseAdapter gooseAdapter = new GooseAdapter(new Goose());System.out.println("使用装饰器模式后,统计叫的次数,不包含天鹅,同时使用了工厂模式产生鸭子");simulate(redheadDuck);simulate(mallarDuck);simulate(rubberDuck);simulate(duckCall);simulate(gooseAdapter);System.out.println("一共叫了 "   QuackCounter.getQuacks()   " 次");}private void simulate(Quackable quackable) {quackable.quack();}}

组合模式-管理一群鸭子

需求方又来了,他们想控制不同鸭子群,把鸭子视为一个集合,为了满足能够管理不同鸭群的需求。

还记得么?组合模式允许我们像对待单个对象一样对待集合对象。所以利用组合模式管理一群Quackable再适合不过了。

首先,组合需要和叶子节点元素一样实现相同的接口。这里的「叶节点」就是Quackable

我们用一个 ArrayList保存属于这个组合的Quackable对象,用add()方法新增Quackable对象到组合中。因为鸭群也是Quackable,所以也具备quack()方法,该方法会对整个鸭群产生作用。

/*** 组合模式,管理一群鸭子: 对待单个对象一样对待集合对象* 组合需要和叶子节点一样实现相同的接口,这里的叶子节点就是 Quackable*/
public class Flock implements Quackable {private List<Quackable> quackers = new ArrayList<>();public void add(Quackable quackable) {quackers.add(quackable);}@Overridepublic void quack() {for (Quackable quackable : quackers) {quackable.quack();}}
}

我们的组合好了,现在要修改模拟器实现鸭群定义与管理,和之前一样。

  1. 首先创建所有的Quackable对象。
  2. 在创建不同的组合Flock鸭群,然后将对应的鸭子放入鸭群。
  3. 最后就能根据组合的鸭群分类测试鸭子满屏飞以及控制不同的鸭群行为了。
public class DuckSimulation {public static void main(String[] args) {DuckSimulation simulation = new DuckSimulation();AbstractDuckFactory duckCountFactory = new DuckCountFactory(new DuckFactory());simulation.simulate(duckCountFactory);}/*** 模拟屏幕展示功能*/private void simulate(AbstractDuckFactory duckFactory) {Quackable redheadDuck = duckFactory.createRedheadDuck();Quackable mallarDuck = duckFactory.createMallarDuck();Quackable rubberDuck = duckFactory.createRubberDuck();Quackable duckCall = duckFactory.createDuckCall();//不想把天鹅的叫声统计,所以不用装饰器装饰GooseAdapter gooseAdapter = new GooseAdapter(new Goose());System.out.println("----使用装饰器模式后,统计叫的次数,不包含天鹅,同时使用了工厂模式产生鸭子---");System.out.println("--使用组合模式管理鸭子群--");// 主要鸭子群Flock flockOfDucks = new Flock();flockOfDucks.add(redheadDuck);flockOfDucks.add(mallarDuck);flockOfDucks.add(rubberDuck);flockOfDucks.add(duckCall);flockOfDucks.add(gooseAdapter);// 绿头鸭群Flock mallarFlock = new Flock();Quackable mallarDuck1 = duckFactory.createMallarDuck();Quackable mallarDuck2 = duckFactory.createMallarDuck();Quackable mallarDuck3 = duckFactory.createMallarDuck();Quackable mallarDuck4 = duckFactory.createMallarDuck();mallarFlock.add(mallarDuck1);mallarFlock.add(mallarDuck2);mallarFlock.add(mallarDuck3);mallarFlock.add(mallarDuck4);System.out.println("----主要鸭子群模拟器----");simulate(flockOfDucks);System.out.println("---绿头鸭群模拟---");simulate(mallarFlock);System.out.println("一共叫了 "   QuackCounter.getQuacks()   " 次");}private void simulate(Quackable quackable) {quackable.quack();}}

观察者模式-观察特定鸭子叫

组合模式让我们很好的管理鸭群,但是现在产品经理又有一个相反的需求:我们也需要追踪个别鸭子,当它呱呱叫鹅时候我们能够收到通知。

同学们是不是想到观察和模式,当感兴趣的某个事件发生的时候我们就收到通知。就像我们订阅的公众号发送消息,那么就通知。

被观察者QuackObservable

首先我们需要定义被观察者角色,提供「注册观察者」、「移除观察者」、「通知观察者」方法。任何想被观察的Quackable都要实现该接口,任何注册到QuackObservable的观察者QuackObserver都会收到呱呱叫通知,晒后我们会定义观察者。

/*** 被观察者:需要管理观察者与通知观察者*/
public interface QuackObservable {/*** 注册观察者* @param observer*/void registerObserver(QuackObserver observer);/*** 移除观察者* @param observer*/void removeObserver(QuackObserver observer);/*** 通知观察者*/void notifyObservers();
}

现在我们需要把所有鸭子实现该接口成为被观察者,从而使得我们可以观察呱呱叫。所以我们干脆让Quackable来继承QuackObservable接口。我们必须确认所有实现Quackable的具体类能够扮演被观察者角色。

/*** 呱呱叫接口,继承被观察者接口,让所有实现了 Quackable 的实现类能够扮演被观察者*/
public interface Quackable extends QuackObservable {/*** 呱呱叫*/void quack();
}

ObservableDelegate辅助类

由于所有的鸭子都实现了Quackable接口,而该接口又继承了QuackObservable被观察者接口。所以每个鸭子类都需要实现注册、通知、取消注册的代码。我们不这么干,抽出一个辅助类ObservableDelegate封装「注册」、「通知」、「取消注册」功能,然后和QuackObservable组合在一起,这样只需要一份代码即可,QuackObservable的所有调用都委托到ObservableDelegate辅助类。

在构造方法中我们传入QuackObservable,好让观察者知道是哪个对象在呱呱叫。

/*** 实现被观察者接口,与 QuackObservable 组合在一起,这样我们只需要一份代码,QuackObservable 的所有调用都委托给* Observable 辅助类*/
public class ObservableDelegate implements QuackObservable {private List<QuackObserver> observerList = new ArrayList<>();private QuackObservable duck;private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();public ObservableDelegate(QuackObservable duck) {this.duck = duck;}@Overridepublic void registerObserver(QuackObserver observer) {ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();writeLock.lock();try {observerList.add(observer);} finally {writeLock.unlock();}}@Overridepublic void removeObserver(QuackObserver observer) {ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();writeLock.lock();try {observerList.remove(observer);} finally {writeLock.unlock();}}@Overridepublic void notifyObservers() {ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();readLock.lock();try {//通知所有的观察者observerList.forEach(item -> item.update(duck));} finally {readLock.unlock();}}
}

辅助类实现了所有必要的功能,我们只要把它插进一个类就可以将工作委托到 ObservableDelegate。

接下来我们整合 ObservableDelegateQuackable使得 Quackable的注册于通知都委托到辅助类。所以每个Quackable的实现类都应该持有ObservableDelegate的实例。接下来我们改造鸭子实现类。

public class MallarDuck implements Quackable {private QuackObservable observableDelegate;public MallarDuck() {this.observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {System.out.println("标准绿头鸭呱呱叫...");//当呱呱叫的时候让观察者知道notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}/*** 鸭子叫模拟器*/
public class DuckCall implements Quackable {/*** 持有 QuackObservable 的引用,将 委托给辅助类实现*/private QuackObservable observableDelegate;public DuckCall() {// 委托给观察者辅助类this.observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {System.out.println("鸭子模拟器叫...");//当呱呱叫的时候让观察者知道notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}public class RedheadDuck implements Quackable {private QuackObservable observableDelegate;public RedheadDuck() {this.observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {System.out.println("红头鸭呱呱叫...");//当呱呱叫的时候让观察者知道notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}/*** 橡皮鸭*/
public class RubberDuck implements Quackable {private QuackObservable observableDelegate;public RubberDuck() {this.observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {System.out.println("橡皮鸭吱吱叫...");//当呱呱叫的时候让观察者知道notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}

还有我们的适配器、以及鸭子叫计数器也是都把被观察者核心代码功能调用委托给辅助类

/*** 将天鹅适配成鸭子*/
public class GooseAdapter implements Quackable {/*** 持有被修饰的对象*/private Goose goose;private QuackObservable observableDelegate;public GooseAdapter(Goose goose) {this.goose = goose;observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {goose.honk();//当呱呱叫的时候让观察者知道notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}/*** 装饰器模式,发出叫声的时候同时记录次数.这样我们就不必修改每个鸭子发出声音的方法*/
public class QuackCounter implements Quackable {private Quackable quack;private static AtomicInteger atomicInteger = new AtomicInteger(0);public QuackCounter(Quackable quack) {this.quack = quack;}@Overridepublic void quack() {quack.quack();atomicInteger.incrementAndGet();}public static AtomicInteger getQuacks() {return atomicInteger;}@Overridepublic void registerObserver(QuackObserver observer) {quack.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {quack.removeObserver(observer);}@Overridepublic void notifyObservers() {quack.notifyObservers();}
}

以及之前定义的鸭群,假如我们也想观察鸭群的叫通知,所以鸭群也要变成被观察者,同时将调用委托给

ObservableDelegate

public class Flock implements Quackable {private List<Quackable> quackers = new ArrayList<>();private QuackObservable observableDelegate;public void add(Quackable quackable) {quackers.add(quackable);observableDelegate = new ObservableDelegate(this);}@Overridepublic void quack() {for (Quackable quackable : quackers) {quackable.quack();}notifyObservers();}@Overridepublic void registerObserver(QuackObserver observer) {quackers.forEach(item -> item.registerObserver(observer));observableDelegate.registerObserver(observer);}@Overridepublic void removeObserver(QuackObserver observer) {quackers.forEach(item -> item.removeObserver(observer));observableDelegate.removeObserver(observer);}@Overridepublic void notifyObservers() {observableDelegate.notifyObservers();}
}

观察者-QuackObserver

最后、我们要准备观察了,现在需要一些观察者。首先就从定义QuackObserver接口开始,它只有一个方法update(QuackObservable duck),传入的就是呱呱叫对象。

/*** 鸭子观察者,当被通知的时候执行update*/
public interface QuackObserver {/*** @param duck 正在呱呱叫的对象*/void update(QuackObservable duck);
}

现在我们来实现一个观察者观察呱呱叫,当收到通知的时候我们就打印下是谁叫的。

/*** 呱呱叫观察者,观察感兴趣的鸭子*/
public class Quackologist implements QuackObserver {@Overridepublic void update(QuackObservable duck) {System.out.println("Quackologist: "   duck   " just quacked。");}
}

屏幕模拟器

大功告成,我们只要在模拟器上创建观察者,并把观察者注册到感兴趣的被观察者中就实现了。

public class DuckSimulation {public static void main(String[] args) {DuckSimulation simulation = new DuckSimulation();AbstractDuckFactory duckCountFactory = new DuckCountFactory(new DuckFactory());simulation.simulate(duckCountFactory);}/*** 模拟屏幕展示功能*/private void simulate(AbstractDuckFactory duckFactory) {Quackable redheadDuck = duckFactory.createRedheadDuck();Quackable mallarDuck = duckFactory.createMallarDuck();Quackable rubberDuck = duckFactory.createRubberDuck();Quackable duckCall = duckFactory.createDuckCall();//不想把天鹅的叫声统计,所以不用装饰器装饰GooseAdapter gooseAdapter = new GooseAdapter(new Goose());System.out.println("----使用装饰器模式后,统计叫的次数,不包含天鹅,同时使用了工厂模式产生鸭子---");System.out.println("--使用组合模式管理鸭子群--");// 主要鸭子群Flock flockOfDucks = new Flock();flockOfDucks.add(redheadDuck);flockOfDucks.add(mallarDuck);flockOfDucks.add(rubberDuck);flockOfDucks.add(duckCall);flockOfDucks.add(gooseAdapter);// 绿头鸭群Flock mallarFlock = new Flock();Quackable mallarDuck1 = duckFactory.createMallarDuck();Quackable mallarDuck2 = duckFactory.createMallarDuck();Quackable mallarDuck3 = duckFactory.createMallarDuck();Quackable mallarDuck4 = duckFactory.createMallarDuck();mallarFlock.add(mallarDuck1);mallarFlock.add(mallarDuck2);mallarFlock.add(mallarDuck3);mallarFlock.add(mallarDuck4);//观察者模式观察指定鸭子的叫,flockOfDucks 被观察者注册了 一个观察者System.out.println("====观察者模式 start===");flockOfDucks.registerObserver(new Quackologist());System.out.println("----主要鸭子群模拟器----");simulate(flockOfDucks);System.out.println("---绿头鸭群模拟---");simulate(mallarFlock);System.out.println("一共叫了 "   QuackCounter.getQuacks()   " 次");}private void simulate(Quackable quackable) {quackable.quack();}}

主要的改动就是

flockOfDucks.registerObserver(new Quackologist());创建观察者,并且观察 flockOfDucks这个鸭群的呱呱叫情况。

总结

最后我们用这个例子主要是打开读者的思维,遇到不同场景根据设计模式的特性便可以将问题迎刃而解,而且代码也变得优雅、高内聚低耦合,代码也得到了复用。

从一开始的鹅适配-「适配器模式」,再到为鸭子叫计数功能增强使用「装饰器模式」,接着创建很多鸭子。就想到了创建型模式「工厂模式」,为了管理鸭群-则想到了「组合模式」,最后想要观察特定鸭子叫,便很快的使用了观察者模式、同时还运用了「委托模式」使得注册观察的代码复用。

若对使用到的设计模式不熟悉可以阅读历史文章了解,欢迎大家提出意见以及指正。

关注公众号JavaStorm,更多干货

关注公众号 JavaStorm 随手掌握精彩干货

设计模式之-降龙十八掌相关推荐

  1. design pattern Builder 生成器设计模式

    其实设计模式可以学习很有趣,你并不需要有这么难啃旱地FOG对我来说,当然,这些都是健康的骨骼啃啃. 在本文中,建造者模式设计一个搞笑的一幕.根据这一模型来学习功夫的方法,哈哈. 基类的第一,设计.那么 ...

  2. design pattern Builder 建造者设计模式

    其实设计模式可以学的很有意思的,不需要非得如此硬枯燥地去啃FOG的大部头,当然这些骨头啃啃也健康. 本文利用建造者模式设计一个有趣的场景,一个利用这个模式去学功夫的过程,呵呵. 首先设计一个基类,学功 ...

  3. 降龙十八掌-程序员篇

    前言: Long long ago,my boss 推荐 me a book called <Unix编程艺术>,本人易脑热,回家就京东了一本,然后简单看了眼目录就放在地板上挂灰了.几个月 ...

  4. 设计模式 策略模式 以角色游戏为背景

    今天不想写代码,给大家带来一篇设计模式的文章,帮助大家可以把系统组织成容易了解.容易维护.具有弹性的架构. 先来看看策略模式的定义: 策略模式(Strategy Pattern):定义了算法族,分别封 ...

  5. 大数据技术●降龙十八掌【目录】

    降龙十八掌这门惊世武功在几百年前销声匿迹,时光如箭,岁月如梭,到了21世纪10年代又突然出现在某宝,这势必将引起武林中的又一轮血雨腥风. <降龙十八掌>这次重出江湖将不同凡响,因为它这次用 ...

  6. 程序员内功-设计模式篇

    一. 什么是设计模式 纠结了好久,今天终于下定决心开始写设计模式系列,因为这个系列章节确实不好写,在这之前,也看了好多关于设计模式的博客.视频.书籍等,最后结合自己的理解,亲自动手实操代码,完成该章节 ...

  7. 设计原则——设计模式基础

    在讲设计原则之前,我先强制灌输大家一波鸡汤,提倡 面向接口编程,代码的设计更重要的是考虑以后的扩展和可维护性 大家带着这样的思维来学习设计模式以及设计原则,慢慢就意会这波毒鸡汤了. 先声明一点就是老衲 ...

  8. 写了这么多年代码,你真的了解设计模式么?

    昨天和同事聊到最近他要做的一个培训,大概的课程是这样的: 第一天: 上午:面向对象原则(OO+SOLID ) 下午:设计模式(Design Pattern) 第二天: 上午:简单设计(SimpleDe ...

  9. 【设计模式】从菜鸟到大鸟之23个模式整体观

    一.前排感受 用了三个星期的时间终于拜读完了<大话设计模式>. 其中书读了三遍,第一遍快速阅读,丛中获得了一个整体的大框架:第二遍仔细阅读,讲书中的所有的例子都动手操作了,不但熟悉运用了C ...

最新文章

  1. NHibernate学习手记(3) - NH的配置信息
  2. 初识50个Linux命令
  3. 3D 服务器端以向量计算为主的角色位置的算法
  4. 解读三种虚拟化之路连载一:x86虚拟化概述
  5. CUDA peer to peer多GPU间内存copy技术
  6. JAVA Timer 定时器
  7. 从 0 经验到成为全球第一模组生产商,日海智能的「非典型」物联网之路
  8. Python中的signal模块和Ctrl+C操作
  9. 软考高项论文写作技巧
  10. 虚拟机安装linux输入密钥,远程连接虚拟机并做密钥认证
  11. 创建VSIX项目模板
  12. JDK 安装教程——图文细讲
  13. 线下活动报名|增长骇客:如何利用数据「玩」出新意
  14. Python的模块和包管理
  15. Python打开电脑文件夹
  16. 运行时服务(二)、warnings模块
  17. ppt中的流程图怎么整体移动_PPT中绘流程图
  18. 三,天猫精灵SDK驱动开发板LED
  19. 艾宾浩斯遗忘曲线PHP,艾宾浩斯遗忘曲线
  20. G003-181-01

热门文章

  1. JAVA基础(三)——服务器操作系统、Java开发环境、Java技术架构、定义Java类及其命名规范、Java注释方式
  2. 程序包不存在解决方案
  3. 程序人生 - 关于茶叶的冷知识,不懂这些,千万别说你懂茶!
  4. 锁机制(自旋锁-乐观锁-悲观锁)
  5. 钻木取火完全攻略——不再是纸上谈兵…
  6. 黑鲨4s和4spro的区别
  7. Beyond 海阔天空 翻唱
  8. python3.6.7安装步骤
  9. 6.6.4 行政处罚记录
  10. 【SOA】从单体架构到分布式微服务架构