网站怎么做短信营销/网络营销系统
文章目录
- 适配器模式
- 组合模式
- 装饰模式
- 代理模式
- 什么时候使用代理模式
- 享元模式
- 外观模式(门面模式)
- 桥梁模式
适配器模式
适配器是一个接口转换器,用于在接收不同的输入时,得到一致的输出。
在java中,可以这样理解:使拥有不同接口的实现类,在同一个接口下实现一致的输出。
一般来说,适配器模式并不是在开发初期需要考虑的设计模式。因为这时候我们只会有一套工具类,不需要做适配。但是随着项目的推进,可能会加入一些其他的包。若想让它们实现同一个接口,就可以考虑使用适配器模式了。
适配器的实现方法不唯一,只要实现让适配器类在不同输入下完成一致的输出即可。具体是用继承还是持有对象的方法,可以视情况而定。
package blog.java.pattern.creater.adapter;public class AdapterTest{public static void main(String[] args) {//测试System.out.println(new CommonAdapter_forExtend().doSomething());System.out.println(new CommonAdapter_forInclude(new NewClass()).doSomething());}
}interface IOld{public int doSomething();} //老接口
interface INew{public int doAnything();} //新接口class OldClass implements IOld{ //老实现类public int doSomething() {return 1;}}
class NewClass implements INew{ //新实现类public int doAnything() {return 2;}}
/**
实用类继承的方法来实现。使NewClass拥有了IOld的方法。*/
class CommonAdapter_forExtend extends NewClass implements IOld{public int doSomething() {//新的实现。内容可能会根据需要做一些更改。return super.doAnything() * 2;}
}
/**
持有对象的方式实现*/
class CommonAdapter_forInclude implements IOld{private IOld iOld;private INew iNew;CommonAdapter_forInclude(IOld iOld){this.iOld = iOld;}CommonAdapter_forInclude(INew iNew){this.iNew = iNew;}public int doSomething() {if(this.iOld != null)return this.iOld.doSomething();elsereturn this.iNew.doAnything() * 2;}}
观察代码可以发现,在适配过程中,无论是OldClass
还是 NewClass
都不需要做修改便实现了目的,这就是适配器写法的作用。
继承是一个很方便的机制,但是在大多数情况下都很危险,慎用!
组合模式
一句话来概括:对一组接口“提取公因式”。
恩,没了。树形结构?那是什么,我不知道。
对于一组类所持有的接口,若它们有共同的方法,可以尝试将这些共有的方法提取出来组建新的接口。写一个简单的例子。
package blog.java.pattern.composite;public class CompositeTest {}interface IA{public void doA();public void doCommon();}
interface IB{public void doB();public void doCommon();}
interface IC{public void doC();public void doCommon();}
//↑↑↑↑↑原来的设计↑↑↑↑↑//↓↓↓↓↓↓新的设计↓↓↓↓↓↓
interface IA_New{public void doA();}
interface IB_New{public void doB();}
interface IC_New{public void doC();}
interface ICommon{public void doCommon();}
对于这种结构的接口,一个很自然的想法就是将共有的方法写到一个父类中,这就是组合模式最基本的写法。这部分的代码就不写了。
再来看一下上面的写法(IA,IB,IC的部分),将同样的方法放到不同的接口,这无疑是冗余。对于这样的类,不只是第一次编写,在日后的维护中都会成为大麻烦。
那么什么样的一组类会拥有这种形式的接口呢?所有类都有共性,很明显,那就是有所属关系的一组类。当这组类有更复杂的层次时,也就是说拥有多层的所属关系时,这种结构又被称为树形结构。这也就是组合模式通常的使用场景。
很多文章都是从“树形结构”出发去讲解组合模式的,不过换个角度看,这只是一种最基本思想(消除冗余)的具体实现罢了。
装饰模式
对于一个方法,如果想要动态的在这个方法的执行前后添加多个方法,可以考虑使用装饰模式。
实现方法简单来说就是,装饰类与被装饰类实现同一个接口,并且持有一个被实现类的对象。装饰类在自己的实现方法中调用内部的被装饰类对象的方法,并在此前后添加自己特有的方法。
由于装饰类拥有一样的接口,它们之间可以相互调用。这就导致了它的写法与执行顺序看起来比较难懂。它的执行就像一种抽象的递归一样,在同接口的类之间递归调用。
package blog.java.pattern.decorator;public class DecoratorTest {public static void main(String[] args) {IInterface ii = new BaseClass();ii = new DecoratorBefore(ii);ii = new DecoratorAfter2(ii);ii = new DecoratorAfter(ii);ii.baseMethod();System.out.println("-------------------");//与上面的写法等效,按喜好选择。new DecoratorAfter(new DecoratorAfter2(new DecoratorBefore(new BaseClass()))).baseMethod();}
}interface IInterface{public void baseMethod();} //待装饰方法接口class BaseClass implements IInterface{public void baseMethod() { //待装饰方法System.out.println("do base method ");}
}abstract class Decorator extends BaseClass{private IInterface iInterface;public Decorator(IInterface iInterface){this.iInterface = iInterface;}public void baseMethod() { //装饰类共有的方法,提出来放到了父类中。this.iInterface.baseMethod();}
}class DecoratorBefore extends Decorator{//装饰类1public DecoratorBefore(IInterface iInterface) {super(iInterface);}private void doSomethingBefore(){System.out.println("do something before ");}public void baseMethod() {this.doSomethingBefore();super.baseMethod();}
}class DecoratorAfter extends Decorator{//装饰类2public DecoratorAfter(IInterface iInterface) {super(iInterface);}private void doSomethingAfter(){System.out.println("do something1 after ");}public void baseMethod() {super.baseMethod();this.doSomethingAfter();}
}class DecoratorAfter2 extends Decorator{//装饰类3public DecoratorAfter2(IInterface iInterface) {super(iInterface);}private void doSomethingAfter(){System.out.println("do something2 after ");}public void baseMethod() {super.baseMethod();this.doSomethingAfter();}
}
装饰模式的精髓就在于我不只可以这样写
IInterface ii = new BaseClass();ii = new DecoratorBefore(ii);ii = new DecoratorAfter2(ii);ii = new DecoratorAfter(ii);ii.baseMethod();
还可以这样写
IInterface ii = new BaseClass();ii = new DecoratorBefore(ii);ii = new DecoratorAfter2(ii);ii = new DecoratorBefore(ii);ii = new DecoratorAfter(ii);ii = new DecoratorBefore(ii);ii.baseMethod();
可以自由的按照需要去组合。
代理模式
我已经写好了一个对象,但是却不准备直接对其进行操作。这时可以考虑使用代理模式。
package blog.java.pattern.proxy;public class Test {public static void main(String[] args) {IInterface proxy = new Proxy(new BaseClass());proxy.doA();}
}interface IInterface{public void doA();public void doB();
}
class BaseClass implements IInterface{public void doA() {}public void doB() {}
}
class Proxy implements IInterface{//代理类private IInterface proxy;public Proxy(IInterface proxy){this.proxy = proxy;}public void doA() {this.proxy.doA();}public void doB() {this.proxy.doB();}
}
什么时候使用代理模式
- BaseClass类是一个不稳定因素。它可能会追加一些新功能(尤其是在某些方法的执行前后添加,就像aop一样),也可能它的代码本身写的很糟糕,我不想直接使用。这时可利用代理模式将调用者与对象解耦的特点,方便修改。
- 想让BaseClass这样的对象延迟加载。原因与实现方法与单例模式中的几乎一样,就不写实现了。
- 不能或者不想让调用者直接使用对象。主要出现在远程调用上。
享元模式
通俗点说,享元模式就是一个字面意思上的共享池。
有一组对象,它们包含有一样的内部对象。这时就可以把它们提取出来放入共享池中。
package blog.java.pattern.flyweight;import java.util.HashMap;
import java.util.Map;public class Test {public static void main(String[] args) {FlyWeight f1 = Factory.getFlyWeight("f1");FlyWeight f2 = Factory.getFlyWeight("f2");FlyWeight f3 = Factory.getFlyWeight("f1");FlyWeight f4 = Factory.getFlyWeight("f1");System.out.println(f1.shareObj);System.out.println(f2.shareObj);System.out.println(f3.shareObj);System.out.println(f4.shareObj);}
}class FlyWeight{String flag; //标识对象Object shareObj; //共享对象Object unShareObj; //非共享对象public FlyWeight(String flag, Object shareObj) {this.flag = flag;this.shareObj = shareObj;}
}class Factory{ //工厂类private static Map<String, Object> map = new HashMap();public static FlyWeight getFlyWeight(String flag){Object temp = map.get(flag);if(temp == null){temp = new Object();map.put(flag, temp);}return new FlyWeight(flag, temp);}
}
上面的例子中,假定如果flag
相同,那么它们就有一样的shareObj
,并且这个shareObj
是一个逻辑上允许共享的对象。
在创建4个FlyWeight
的实例后,只有2个shareObj
的实例存在于内存中。
相比于一般的使用方法,享元模式会使程序变得更复杂,并且几乎不会增强功能性。因此,享元模式主要适用于需要降低内存使用的情况下。
外观模式(门面模式)
我想进行一个复杂操作,但是不想管里面的实现,想要只通过一个调用就能得到结果。这时用外观模式。
这个应该所有人都用过,我们平时写的各种工具类就是一个外观模式。不多说了。
package blog.java.pattern.facade;public class FacadeTest {public static void main(String[] args) {new Facade().doSomething("do something");}
}class Facade{public void doSomething(Object obj){System.out.println("do something A");System.out.println("do something B");System.out.println(obj);System.out.println("do something C");System.out.println("do something D");}
}
桥梁模式
从写法上看,它跟策略模式没什么区别,就是增加了一个抽象父类。想要达到的效果也一样,就是解耦。
为了让写出的代码看起来更像桥梁模式,需要把抽象出来的,不会改变的部分拿到父类中去。
package blog.java.pattern.bridge;public class Bridge {public static void main(String[] args) {BaseClass baseClass = new BaseClass(new MethodClass());baseClass.doSomething();}
}interface IInterface{public void doA();}abstract class AbstractClass{IInterface iInterface;public AbstractClass(IInterface iInterface){this.iInterface = iInterface;}public void doSomething(){ //抽象出的业务System.out.println("do 1");this.iInterface.doA();System.out.println("do 2");}
}class BaseClass extends AbstractClass{public BaseClass(IInterface iInterface) {super(iInterface);}
}class MethodClass implements IInterface{//具体实现public void doA() {System.out.println("do A");}
}
一般在BaseClass与MethodClass同时为不安定因素是优先考虑使用桥梁模式。