spring是一种非常优秀的框架,其中有很多优秀的设计思想的体现,提前学习下spring中使用的设计模式,可以为以后学习spring源码打好基础。注:一下所写内容中的例子,代码参考《大话设计模式》这本书。
顾名思义,简单工厂模式就好比现在的小工厂,生产一种产品,分成几个部分,由几个生产车间分别完成,最后组合到一起形成最后的产品。简单工厂模式很好的体现了单一职责这一设计原则。
①首先是一个个小车间,他们可以抽象出来,形成一个抽象类。
下面是一个实现加减运算的用简单工厂模式实现的代码,定义运算操作
public interface Operation {
public double getResult(double num1, double num2);
}
②然后是每个具体的车间去各自去生产自己要生产的产品。去实现这个抽象类。用加减法 去实现这个运算
public class OperationAdd implements Operation{
public double getResult(double num1, double num2) {
return num1 + num2;
}
}
public class OperationSub implements Operation{
public double getResult(double num1, double num2) {
return num1 - num2;
}
}
③接着各个车间的产品生产好了,这时候就要看需要哪个车间的产品了。根据运算符来选择对应的运算类
public class OperationFactory {
public static Operation createOperation(String operate) {
switch(operate) {
case "+":
return new OperationAdd();
case "-":
return new OperationSub();
default:
return null;
}
}
}
④看下拿过来的产品合不合格,能不能用了。 运算结构的测试。
public class SimpleFactoryTest {
public static void main(String[] args) {
Operation ope = null;
ope = OperationFactory.createOperation("+");
System.out.println(ope.getResult(10,9));
}
}
这种模式就好像平时在商场购物时,遇到的各种打折、满减、积分等促销活动。这些相当于一个个的规则,都是用来最后的结算的,只是实现不同。规则之间可以相互替换。
策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
用商场购物结算的场景代码来演示。
①首先收费的抽象类
public abstract class CashSuper {
public abstract double acceptCash(double money);
}
② 然后是各种收费计算的规则,它们都要继承收费的抽象父类
正常收费
public class CashNormal extends CashSuper{
public double acceptCash(double money) {
return money;
}
}
满减
public class CashReturn extends CashSuper{
private double moneyCondition = 0.00d;
private double moneyReturn = 0.00d;
CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
public double acceptCash(double money) {
if (money >= moneyCondition) {
return money - moneyReturn;
}
return money;
}
}
③ 定义一个Context 辅助类,来持有 收费的收费类
public class CashContext {
// 这里持有了策略父类的引用
private CashSuper cs = null;
CashContext (CashSuper cs) {
this.cs = cs;
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
④ 测试下效果
public class CashTest {
public static void main(String[] args) {
CashContext cashContext = null;
cashContext = new CashContext(new CashNormal());
double moneyNormal = cashContext.getResult(700);
System.out.println("-------" + moneyNormal);
cashContext = new CashContext(new CashReturn(500,200));
double moneyReturn = cashContext.getResult(700);
System.out.println("-------" + moneyReturn);
}
}
装饰者模式中,其实对于被装饰者,无需要知道装饰对象的存在,装饰对象中如果需要使用被装饰对象中的方法,可以维护一个被装饰者的引用,如果单纯的是对被装饰者的方法进行增强操作,可以不用维护引用,直接覆盖掉被装饰对象中的方法即可,这也是其不同于适配器模式的地方,适配器模式中,需要通过某种方式维护被装饰者的引用。总体来说,装饰者模式中,装饰对象与被装饰者是一个is-a的关系,而适配器模式中,似乎是has-a的关系。一定层度上来说,装饰者模式好像就是多继承的一种实现而已
装饰器模式结构图
Component 是定义的一个对象接口,可以给这些对象动态的添加职责,ConcreteComponent 是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator ,装饰抽象类,继承了 Component ,从外类来扩展 Component 类的功能,但对于Component 来说,是无需知道 Decorator的存在的。 ConcreteDecorator 是具体的装饰对象,起到给 Component 添加职责的功能。
如果只有一个ConcreteComponent 类而没有抽象的Component 类,那么 Decorator 类可以是 ConcreteComponent 的一个子类。同样如果只有一个 ConcreteDecorator 类,那就没有必要建立一个单独的 Decorator 类,而可以把 Decorator 盒和 ConcreteDecorator 的责任合并成一个。
下面是用 给人穿衣服这个场景来演示 装饰模式
① 首先是创建 Component 类,在此场景对应为 Person 类,因为 不将人再区分成不同的人,所以将 ConcreteComponent 和 Component 的功能合并
/**
*
* @author Administrator
* 被修饰的对象, 使用给人穿衣服来演示装饰模式
*/
public class Person {
private String name;
Person() {}
Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
② 接着是 各种衣服的父类,对应 Decorator 类,在这里 通过类属性来持有 person 类的 引用
/**
*
* @author Administrator
* 各种衣服的的父类
*/
public class Finery extends Person{
// 子类都会通过 继承得到 component
protected Person component;
// 会被子类继承,然后去持有不同的 要被装饰的对象
public void decorate(Person component) {
this.component = component;
}
@Override
public void show() {
if (component != null) {
component.show();
}
}
}
③ 各种具体的衣服 ,对应 ConcreteDecorator 这个类
/**
*
* @author Administrator
* 具体服饰
*/
public class BigTrouser extends Finery{
@Override
public void show() {
System.out.println("大裤子");
if (component != null) {
component.show();
}
}
}
/**
*
* @author Administrator
* 具体服饰
*/
public class Tshirt extends Finery{
public void show() {
System.out.println("大T恤");
if (component != null) {
component.show();
}
}
}
④ 测试下
public class DecoratorTest {
public static void main(String[] args) {
Person ps = new Person("小明");
Tshirt ts = new Tshirt();
BigTrouser bt = new BigTrouser();
ts.decorate(ps);
bt.decorate(ts);
bt.show();
}
}
测试结果:
观察者模式 是 在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
观察者模式结构图
该模式包含四种角色
下面使用给微信订阅用户推送消息的方式来演示这种模式
①首先定义微信服务器抽象类,来注册用户,删除用户,发布消息,相当于主题,抽象被观察者
/*
* 模拟微信服务器的抽象接口
*/
public interface AbstractWeChat {
//用户注册
public void registerUser(AbstractUser auser);
// 用户注销
public void deleteUser(AbstractUser auser);
// 通知用户
public void notifyUser(String msg);
}
②、定义用户的抽象接口,相当观察者。接到主题发布的消息后,执行相应的操作
/**
*
* @author Administrator
* 用户的抽象接口
*/
public interface AbstractUser {
public void update(String msg);
}
③ 、模拟微信服务器,实现抽象被观察者接口
public class WeChatServer implements AbstractWeChat{
// 定义一个list 来持有 注册的用户
List userList = new ArrayList();
// 注册用户
public void registerUser(AbstractUser auser) {
this.userList.add(auser);
}
// 删除用户
public void deleteUser(AbstractUser auser) {
if (!userList.isEmpty()) {
this.userList.remove(auser);
}
}
// 通知用户
public void notifyUser(String msg) {
for (AbstractUser abstractUser : userList) {
abstractUser.update(msg);
}
}
}
④、定义具体的观察者,
public class User implements AbstractUser{
private String name;
public User(String name) {
this.name = name;
}
public void update(String msg) {
System.out.println("好的,"+name + "已经收到消息:" + msg);
}
}
⑤测试类
public class ObserverTest {
public static void main(String[] args) {
//定义用户
User xiaowang = new User("小王");
User zhangsan = new User("张三");
User laoli = new User("老李");
// 定义微信的服务器
WeChatServer wcs = new WeChatServer();
// 注册推送用户
wcs.registerUser(xiaowang);
wcs.registerUser(zhangsan);
wcs.registerUser(laoli);
// 推送消息
wcs.notifyUser("开始学习观察者模式啦!");
// 移除部分用户
wcs.deleteUser(xiaowang);
// 重新推送消息
wcs.notifyUser("新学员开始啦!");
}
}
测试结果:
代理模式简单点说就是本来你要做的事让别人代替你去做。
比如我们在追美女的时候,最好的就是要先搞定她的闺蜜或者小舅子,让他们帮我们传递一些东西。
①首先,我们要是追女孩子,就要给人家送花啊,请人家看电影之类的,先把这些操作抽象出来。
public interface Pursuit {
// 送花
void giveFlower();
// 一起看电影
void watchMovie();
}
② 要想追美女,对人家必要的了解还是要有的,美女类,定义美女的名字
public class BeautyGril {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
③ 定义具体的追求者,他来实现具体的追求动作。
public class HandSomeMan implements Pursuit{
private BeautyGril bg;
HandSomeMan(BeautyGril bg) {
this.bg = bg;
}
public void giveFlower() {
System.out.println(bg.getName()+"送给你花花!");
}
public void watchMovie() {
System.out.println(bg.getName()+"咱们一起去看电影吧!");
}
}
④ 如果你比较害羞,不好意思直接送花,你就可以让她的闺蜜代为转交,也是代理类
public class ProxyMan implements Pursuit{
// 这里需要持有被代理人的引用
private HandSomeMan handSomeMan;
ProxyMan(BeautyGril bg) {
this.handSomeMan = new HandSomeMan(bg);
}
public void giveFlower() {
handSomeMan.giveFlower();
}
public void watchMovie() {
handSomeMan.watchMovie();
}
}
⑤下面来测试下效果
public class ProxyTest {
public static void main(String[] args) {
BeautyGril bg = new BeautyGril();
bg.setName("moli");
ProxyMan xiaojiuzi = new ProxyMan(bg);
//代理的动作
xiaojiuzi.giveFlower();
xiaojiuzi.watchMovie();
};
}