在程序员的世界里,泡妞可真的是一门很大的学问,因为程序员天真单纯腼腆,不懂得套路,嘴巴也不会说,每天都沉浸和陶醉在代码的世界里,不亦乐乎,对于泡妞来说,基本上不怎么会,更不要说屌丝逆袭了,所以跟大家从设计模式的角度分享一下身边一位高人的泡妞绝学,开启小金同学的泡妞之路:
【相遇之观察者模式】
在一个阳光明媚的清晨,桃花那个朵朵开,小金同学走过一座小桥边,遇到了一位弹琴的姑娘,真可谓是暖阳下,我迎芬芳,是谁家的姑娘,我走在了那座小桥上,你抚琴奏忧伤,桥边歌唱的小姑娘 你眼角在流淌,她有着长长的乌黑发,一双眼明亮,风华模样,你落落大方,姑娘你让我心荡漾,小鹿在乱撞呀。如此美人,怎能让小金一人欣赏,所以很多小哥哥,也都注意到了琴声优美的姑娘,姑娘观察到这么多人在关注她,这琴弹奏的越来越美了。后续故事暂且放一放,这里首先跟大家介绍第一个设计模式,观察者模式,上面的场景中,就用到了我们的观察者模式,弹琴的姑娘是被观察者,也是观察者模式中的主题角色,小金和其他的小哥哥就是观察者,美女弹琴,琴声悠扬,主题做出相应的操作,观察者通过眼睛和耳朵都能收到通知。
观察者模式定义:
【观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生改变的时候,会通知所有的观察者对象,让他们能够自动去更新自己】
观察者模式角色:
【抽象主题角色】:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现。
【抽象观察者角色】:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
【具体主题角色】:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
【具体观察者角色】:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现。
观察者模式类图:
场景之代码实现:
定义抽象主题角色:
package com.harderxin.pattern.observer;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 10:42
* @description 定义抽象主题角色
*/
public interface Observed {
/**
* 添加观察者
*
* @param watcher
*/
void addWathcer(Watcher watcher);
/**
* 删除观察者
*
* @param watcher
*/
void removeWatcher(Watcher watcher);
/**
* 通知观察者
*
* @param action
*/
void notifyWatchers(String action);
}
定义抽象观察者角色:
package com.harderxin.pattern.observer;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 10:42
* @description 定义抽象观察者角色
*/
public interface Watcher {
/**
* 观察者收到通知后做出相应操作
*
* @param action
*/
void update(String action);
}
定义具体的主题角色:
package com.harderxin.pattern.observer;
import java.util.ArrayList;
import java.util.List;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 10:55
* @description 定义一个具体的主题角色,场景中弹琴的女孩
*/
public class Girl implements Observed {
// 一个具体的主题角色有很多观察者
List<Watcher> watchers = new ArrayList<>();
@Override
public void addWathcer(Watcher watcher) {
watchers.add(watcher);
}
@Override
public void removeWatcher(Watcher watcher) {
watchers.remove(watcher);
}
@Override
public void notifyWatchers(String action) {
for (Watcher watcher : watchers) {
watcher.update(action);
}
}
}
定义具体的观察者角色:
package com.harderxin.pattern.observer;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 10:58
* @description 定义一个具体的观察者角色
*/
public class Boy implements Watcher {
private String name;
public Boy(String name) {
this.name = name;
}
/**
* 主题发出通知信息,观察者可接收到
*
* @param action
*/
@Override
public void update(String action) {
System.out.println(this.name + " 接收到来自美女的通知:" + action);
}
}
测试类:
package com.harderxin.pattern.observer;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:00
* @description 观察者模式:启动类
*/
public class Main {
public static void main(String[] args) {
// 定义一个主题角色:桥边弹琴的姑娘
Observed girl = new Girl();
// 定义多个观察者角色:小金和很多小哥哥
Watcher boyOne = new Boy("小金");
Watcher boyTwo = new Boy("小华");
Watcher boyThree = new Boy("小鹏");
Watcher boyFour = new Boy("小鑫");
// 小金和小哥哥观察美女弹琴
girl.addWathcer(boyOne);
girl.addWathcer(boyTwo);
girl.addWathcer(boyThree);
girl.addWathcer(boyFour);
// 姑娘弹琴,看到有这么多小哥哥,跟他们打招呼
girl.notifyWatchers("小哥哥们好");
// 小鑫因为要忙着加班,先走一步了,姑娘少了一个观察者
girl.removeWatcher(boyFour);
}
}
【问联系方式之策略模式】
如此美丽的姑娘,小金看的两眼冒金星,心跳砰砰加速,这就是一见钟情的感觉呀,小金的脑袋里就在想怎么能够要到姑娘的微信,于是乎大脑开始对话了:
左脑:你可以直接上去要微信,可是你有这个胆子么?
右脑:他没这个胆子,还是让朋友帮忙问问吧
左脑:可以制造相遇的机会,或者说打听路线之类的
右脑:那都是老套路了,能不能来点新鲜的,比如英雄救美呀
左脑:啊呸,你的更俗
..................
经过左右大脑的一番激烈的斗争,小金同学一脸茫然
好了,在这里,又一个设计模式要诞生了,就是策略模式,问联系方式是需要讲究策略的,好的策略才不会觉得尴尬。
策略模式定义:
【策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户,你可以动态的改变对象的行为】说白了就是策略模式有很多种可选方案,然后你可以在规定的场景中随意选择对应的方案,达到想要的效果。
策略模式角色:
环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。
抽象策略对象:它可由接口或抽象类来实现。
具体策略对象:它封装了实现同不功能的不同算法。
策略模式类图:
场景之代码实现:
定义抽象策略对象:
package com.harderxin.pattern.strategy;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:31
* @description 定义抽象策略对象:泡妞策略
*/
public interface ChaseGirlStrategy {
/**
* 获取联系方式
*
* @return
*/
String getContractWay();
}
定义具体策略对象:
package com.harderxin.pattern.strategy;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:45
* @description 定义具体策略对象:直接上去问
*/
public class OpenStrategy implements ChaseGirlStrategy {
@Override
public String getContractWay() {
return "直接上去问联系方式";
}
}
package com.harderxin.pattern.strategy;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:46
* @description 定义具体策略对象:英雄救美
*/
public class HeroStrategy implements ChaseGirlStrategy {
@Override
public String getContractWay() {
return "英雄救美,然后问联系方式";
}
}
package com.harderxin.pattern.strategy;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:47
* @description 定义具体策略对象:请朋友帮忙
*/
public class FriendStragegy implements ChaseGirlStrategy {
@Override
public String getContractWay() {
return "请朋友帮忙,通过朋友获取联系方式";
}
}
定义环境对象:
package com.harderxin.pattern.strategy;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:50
* @description 定义一个环境对象:只要遇到了喜欢的女孩,随时都是泡妞环境吖
*/
public class ChaseGirlEnviroment {
// 持有泡妞策略的引用
private ChaseGirlStrategy strategy;
public void setStrategy(ChaseGirlStrategy strategy) {
this.strategy = strategy;
}
public String getContractWay() {
return strategy.getContractWay();
}
}
测试类:
package com.harderxin.pattern.strategy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/11 11:30
* @description 策略模式:启动类
*/
public class Main {
public static void main(String[] args) {
// 定义一个泡妞的环境对象:场景中的小桥边
ChaseGirlEnviroment enviroment = new ChaseGirlEnviroment();
// 左脑说:直接上去问微信
ChaseGirlStrategy srategy = new OpenStrategy();
// 将这个策略运用到场景中
enviroment.setStrategy(srategy);
System.out.println(enviroment.getContractWay());
// 右脑说:英雄救美吧
srategy = new HeroStrategy();
// 将这个策略运用到场景中
enviroment.setStrategy(srategy);
System.out.println(enviroment.getContractWay());
}
}
最后小金还是靠自己的才华,在现场厚着脸皮唱了一首情歌《桥边姑娘》拿到了联系方式,那个激动和开心溢于言表。
【约会之装饰模式】
拿到了妹子的联系方式,小金也把策略模式运用到了如何聊天、如何调动妹子情绪、如何展现自己的才华等方面,自古套路得人心啊,经过一段时间的联系,软磨硬泡,妹子终于答应跟小金约会了,地点选在了一家茶餐厅,小金早早的就来约定的地点等候了,并且为了体现自己是个暖男,给妹子点了一杯白开水,然后准备了茶叶包、红糖包、咖啡包,想让妹子根据自己的心情和爱好选择自己喜欢喝的,这就是细节,说不定妹子就被这些小细节感动了呢,妹子如约而至,今天打扮很漂亮,长长的散发,白白的裙子,让小金同学看了春心那个荡漾呀,服务员端上了一杯白开水,让妹子自己天添加喜欢的饮品,妹子会选择哪个呢?好了,有一个设计模式要横空出世了,这就是装饰者模式,这个场景中白开水是具体的构建角色,茶叶、糖、咖啡是装饰角色,用来装饰水,也就是装饰具体的构建角色,那么在装饰模式中又有哪些角色参与呢?
装饰模式定义:
【装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象,又叫做包装模式。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展,是继承关系的一个替代方案】
装饰模式角色:
抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件角色(Concrete Component):定义一个将要接收附加责任的类
装饰角色(Decorator):持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口
具体装饰角色(Concrete Decorator):负责给构件对象贴上附加的责任
装饰模式类图:
场景之代码实现:
定义抽象构建角色:
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:13
* @description 定义抽象构建角色
*/
public interface WaterComponent {
/**
* 提供一个喝的方法
*/
void drink();
}
定义具体构建角色,无论如何这个是基础服务:
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:24
* @description 定义具体构建角色
*/
public class ConcreteWaterComponent implements WaterComponent {
@Override
public void drink() {
System.out.println("喝水");
}
}
定义抽象装饰角色,持有抽象构建角色引用:
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:25
* @description 定义装饰角色:水的装饰
*/
public abstract class WaterAbstractDecorator implements WaterComponent {
// 持有构建对象的引用
private WaterComponent waterComponent;
/**
* 通过构造方法传递给被装饰者
*
* @param waterComponent
*/
public WaterAbstractDecorator(WaterComponent waterComponent) {
this.waterComponent = waterComponent;
}
@Override
public void drink() {
if (null != waterComponent) {
waterComponent.drink();
}
}
}
定义具体装饰角色:
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:30
* @description 定义具体装饰者角色
*/
public class TeaDecorator extends WaterAbstractDecorator {
public TeaDecorator(WaterComponent waterComponent) {
super(waterComponent);
}
/**
* 定义装饰的行为
*/
public void addToDrink() {
System.out.println("加点茶叶");
}
@Override
public void drink() {
addToDrink();
super.drink();
}
}
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:30
* @description 定义具体装饰者角色
*/
public class SugarDecorator extends WaterAbstractDecorator {
public SugarDecorator(WaterComponent waterComponent) {
super(waterComponent);
}
/**
* 定义装饰的行为
*/
public void addToDrink() {
System.out.println("加点糖");
}
@Override
public void drink() {
addToDrink();
super.drink();
}
}
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:30
* @description 定义具体装饰者角色
*/
public class CoffeeDecorator extends WaterAbstractDecorator {
public CoffeeDecorator(WaterComponent waterComponent) {
super(waterComponent);
}
/**
* 定义装饰的行为
*/
public void addToDrink() {
System.out.println("加点咖啡");
}
@Override
public void drink() {
addToDrink();
super.drink();
}
}
测试类:
package com.harderxin.pattern.decorator;
/**
* @author 吴鑫
* @contact [email protected]
* @date 2019/12/12 11:08
* @description 装饰者模式:启动类
*/
public class Main {
public static void main(String[] args) {
WaterComponent component = new ConcreteWaterComponent();
// 喝白开水太枯燥了,来随机装饰一下吧
// 加点茶叶
component = new TeaDecorator(component);
// 加点咖啡
component = new CoffeeDecorator(component);
// 加点糖
component = new SugarDecorator(component);
component.drink();
System.out.println("--------------------------------");
// 下面的写法是不是似曾相识
WaterComponent component2 = new SugarDecorator(new CoffeeDecorator(new TeaDecorator(new ConcreteWaterComponent())));
component2.drink();
}
}
小金和妹子聊得很好,上到天文地理,下到语数外、文物历史、计算机绝学,这把他能的,一下午的聊天过程中,妹子是喝了茶、喝了加糖的咖啡,两人相谈盛欢,空气中弥漫着爱情的味道。