设计模式
创建者模式
单例模式
特点:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
优点:单例模式只会生成一个实例,这样就减少了系统性能的开销,当一个对象的产生需要较多的资源的时候,比如读取配置文件,需要加载其它依赖对象的时候,可以实例化一个对象,然后在应用启动的时候永驻于内存中来进行解决
分类
饿汉式
特点:线程安全-调用效率高,但是,不能延时加载
关键:类加载后,就立即实例化这个对象
private static dog dog1=null;
private static String dog_name="";
static{
if(dog1==null){
dog1=new dog("小花");
}
}
private dog(String dog_name){
this.dog_name=dog_name;
}
public static dog getInstance(){
return dog1;
}
懒汉式
特点:线程安全,调用效率不高,但是可以延时加载
关键:需要时才进行实例化该对象
private static dog dog1=null;
private static String dog_name="";
private dog(String dog_name){
this.dog_name=dog_name;
}
public synchronized static dog getInstance(){
if(dog1==null){
dog1=new dog("小花");
}
return dog1;
}
需要使用方法同步,避免在异步的情况下,多次被创建对象
缺点:并发效率低,调用效率低,每次都需要同步调用(因为使用了synchronized)
双重检测锁式
特点:这个模式将同步内容放在里面的if判断中,提高了执行的效率,不必每次获取对象都需要同步,只有第一次创建对象的时候,才需要同步,其他时候,都不需要了
缺点:由于JVM底层内部模型原因,偶尔会出现问题
public static TestSingleton getInstance() {
if (instance == null) {
synchronized (TestSingleton.class) {
if (instance == null) {
instance = new TestSingleton();
}
}
}
return instance;
}
第一个访问进去创建对象的时候,第二个访问在外面等待,第一个创建好了对象后,第二个进入第一层锁后就拿到了对象,然后跳出返回。
静态内部式
特点:线程安全,调用时效率高,可以延迟加载
关键:只有真正调用getInstance(),才会加载内部类,加载类时时是线程安全的,instance时static final类型,保证了内存中只有这么一个实例的存在,而且只能被赋予一次,从而保证了线程的安全性。从而兼备了并发高效调用和延迟调用的优势
private static class getInst{
public static final dog instance= new dog();
}
public static dog getInstance1(){
return getInst.instance;
}
private dog() {
}
枚举
特点:线程安全,调用效率高,不能延时加载,可以天然的防止反射与反序列化
public enum dog {
INSTANCE;
}
枚举类本身就带有私有得构造方法,每个枚举对象,都会被static以及final修饰。所以枚举天然是单例模式
这几种单例得实现方式,如何选用:
1:在需要延时加载的时候,静态内部类好于懒汉式
2:在不需要延时加载的时候,枚举式好于饿汉式
工厂模式
特点:实例化对象,使用工厂方法,而不是通过new来创建对象,将选择实现类,创建对象统一管理和控制,从而将调用者跟实现类解耦
简单工厂模式
定义一个接口类
public interface Car {
void run();
}
创建两个实体类
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪在跑");
}
}
public class Biyadi implements Car{
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
创建一个工厂类–
public Car creatCar(String cartype){
if(cartype.equalsIgnoreCase("奥迪")){
return new Audi();
}else if(cartype.equalsIgnoreCase("比亚迪")){
return new Biyadi();
}else {
return null;
}
}
工厂方法模式
特点:思想在于解耦合,符合OCP原则(开闭原则)
先创建一个接口类,然后创建一个接口实现类,接着在创建一个工厂接口类,最后创建实现了工厂接口类的实现类,由不同的实现类去创建不同的对象,有新的产品时,再创建相应的工厂接口实现类就好了,不需要再去改前面的代码
实现:
创建一个实现类的接口:
public interface Car {
void run();
}
创建两个实现类
public class Biyadi implements Car {
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪在跑");
}
}
创建工厂接口类:
public interface CarFactory {
Car createCar();
}
创建工厂实现类
public class BydFactory implements CarFactory {
@Override
public Car createCar() {
return new Biyadi();
}
}
public class AudiFactory implements CarFactory {
@Override
public Car createCar() {
return new Audi();
}
}
工厂方法模式与简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类
简单工厂模式与工厂方法模式之间的区别
1:结构复杂度:简单工厂模式只需要一个工厂类就要好了,而工厂方法模式需要随着产品类别的增加,工厂类的数量也随着增加
2:代码复杂度:虽然简单工厂模式,结构上更加简单,但是在代码层面方法因为产品类的增多而变复杂了。而工厂方法模式则相反
3:客户端编程的难度:简单工厂模式因为只有一个类,所以客户端编程的难度比较低,而工厂方法模式,如果产品类比较多,那么也是比较复杂的
抽象工厂
特点:抽象工厂是在工厂模式得基础上,做了一个维度的提升
应用场景:当一个产品有两个维度得特征,而这两个维度又具有层次结构得时候,那么其中一个维度可以作为产品族,而另一个维度可以作为具体的产品。比如说电脑下有不同品牌的电脑,比如戴尔以及小米,三星等。而不同品牌得电脑下,又分为不同型号得电脑。不同的品牌就是一个个的产品族,不同型号的电脑就是具体产品
实现:
创建电脑接口类:
public interface Computer {
void code();
}
电脑接口实现类
//产品族--戴尔品牌
public class DellComputer implements Computer {
@Override
public void code() {
System.out.println("戴尔品牌电脑");
}
}
//产品族下的具体产品--戴尔品牌下的具体型号的电脑
public class Dell_Vostro extends DellComputer {
@Override
public void code() {
super.code();
System.out.println("在Vostro上写代码");
}
}
//产品族下的具体产品--戴尔品牌下的具体型号的电脑
public class Dell_Latitude extends DellComputer {
@Override
public void code() {
super.code();
System.out.println("在Dell_Latitude上写代码");
}
}
生产产品族中具体产品的工厂实现类接口:
public interface AbstractFactory {
Computer getComputer(String computerName);
}
生产产品族中具体产品的工厂实现类:
public class DellFactory implements AbstractFactory{
private String packageName="com.yiyu.factory.obstractFactory2.";
public Computer getComputer(String computerName){
Computer computer=null;
try {
Class aClass = Class.forName(packageName+computerName);
computer = (Computer)aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return computer;
}
}
生产产品族的工厂类:
public class ComputerFactory {
private String packageName="com.yiyu.factory.obstractFactory2.";
public ComputerFactory() {
}
public AbstractFactory getFactory(String type){
AbstractFactory abstractFactory = null;
try {
Class aClass = Class.forName(packageName+type);
abstractFactory = (AbstractFactory)aClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return abstractFactory;
}
}
实现思路:
由生产出产品族(电脑的品牌)的工厂,生产出产品族。再由产品族(电脑品牌下具体型号的电脑)生产出具体的产品。
建造者模式
特点:分离了对象子组件的单独构造和装配,从而可以构造出更为复杂的对象,这个模式适用于,某个对象构建过程比较复杂的情况下使用
由于实现了子组件的创建于装配的分离,也就对象在不同的构造器,相同的装配,可以有所不同。在可以在相同的构造器,不同的装配顺序也会有所不同,也就实现了构建算法,装配算法的解耦合,实现了更好的复用
注:
1:构建器也就是创建子组件的对象
2:装配是指的装配流程和顺序
以建造飞船为例,将飞船各个子部件从工厂创建出来,然后由一个组装中心进行组装成一个飞船。
实现:
创建飞船的实体类
public class AirShip {
private OrbitalModule orbitalModule;
private Engine engine;
private EscapeTower escapeTower;
public void setOrbitalModule(OrbitalModule orbitalModule) {
this.orbitalModule = orbitalModule;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setEscapeTower(EscapeTower escapeTower) {
this.escapeTower = escapeTower;
}
}
创建飞船各个子组件:
创建逃逸塔:
class OrbitalModule{
private String name;
public OrbitalModule(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建轨道舱
class EscapeTower{
private String name;
public EscapeTower(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建发动机
class Engine{
private String name;
public Engine(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
生成创建飞船各个子组件的工厂类接口
public interface AirShipBuilder {
Engine builderEngine();
OrbitalModule builderOrbitalModule();
EscapeTower builderEscapeTower();
}
生成创建飞船各个子组件的工厂实现类
public class AirShip implements AirShipBuilder{
@Override
public Engine builderEngine() {
System.out.println("构建发动机");
return new Engine("yiyuEngine");
}
@Override
public OrbitalModule builderOrbitalModule() {
System.out.println("构建逃逸塔");
return new OrbitalModule("yiyuOrbitalModule");
}
@Override
public EscapeTower builderEscapeTower() {
System.out.println("构建轨道仓");
return new EscapeTower("yiyuEscapeTower");
}
}
创建构造器(装配中心)接口:作用是把各个子组件组装起来
public interface AirShipDirector {
AirShip directAirShip();
}
创建构造器具体实现类
public class AirShipDirector implements AirShipDirector {
private AirShip airShip;
@Override
public AirShip directAirShip() {
Engine engine = yiyuAirShip.builderEngine();
EscapeTower escapeTower = yiyuAirShip.builderEscapeTower();
OrbitalModule orbitalModule = yiyuAirShip.builderOrbitalModule();
AirShip airShip = new AirShip();
airShip.setEngine(engine);
airShip.setEscapeTower(escapeTower);
airShip.setOrbitalModule(orbitalModule);
return airShip;
}
public yiyuAirShipDirector(AirShip airShip) {
this.AirShip = airShip;
}
}
原型模式
特点:
1:就是java中的克隆技术,以某个对象为原型,复制出新的对象,然后具备新对象的所有特点
2:克隆类似于new,但是不同于new,new创建出的对象的属性值都是默认值,而克隆出的对象,将原型对象的一切属性值都拿过来了,一般不会修改原型对象的值,只会在其基础上进行修改
优点:优势是效率高,直接复制,避免了重新构造的过程。跳过代码构建过程,直接内存操作,将内存中的一个对象进行克隆操作
何时使用:通过new产生一个对象需要比较繁琐的数据准备或访问权限,则可以使用原型模式
实现:
克隆分为浅克隆于深克隆(浅拷贝与深拷贝)
先讲讲浅拷贝:
浅克隆:将对象本身直接进行复制操作
需要克隆的实体类,需要实现Cloneable接口(Cloneable是一个空接口,是一个标记接口,表明实现了该接口的类,才能进行克隆操作)
public class Sheep implements Cloneable, Serializable {
private String sname;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object clone = super.clone();
return clone;
}
public Sheep() {
}
public Sheep(String sname, Date birthday) {
this.sname = sname;
this.birthday = birthday;
}
}
clone是Object里的方法,但是使用clone就需要继承Cloneable接口,这是一个规范
这种克隆方法克隆出来的对象,就是浅克隆(浅拷贝),当克隆里属性是一个对象的时候,这个对象的地址也会被克隆过去,也就是说这个属性对象的值发生改变后,那么克隆出来的新对象中的属性对象的值也会发生改变
深拷贝:将对象内部的属性以及方法逐一进行复制操作,也就是对属性对象本身直接克隆出新的一份,与之前的被克隆对象中的属性对象的地址不共用同一个,完全的独立于前一个被克隆对象。
@Override
protected Object clone() throws CloneNotSupportedException {
Object clone = super.clone();
//使用如下代码实现深拷贝
Sheep s=(Sheep)clone;
s.setBirthday((Date)s.birthday.clone());
return s;
}
在克隆实体类对象的时候,将属性对象也克隆一份
注意:
1:如果clone时,属性只是单纯的值,效果都跟深拷贝一样(后面对应值的改变不会引发克隆与被克隆的对象的值改变)
2:而就被复制的对象本身而言,无论本身发生任何变化(被替换了,被置为空),其结果在深拷贝与浅拷贝的情况下都无法影响到复制后的对象
3:如果是赋值操作,那么就是浅拷贝–Sheep clone = xiaoen;
4:原型模式一般很少单独出现,一般是搭配工厂模式进行一起使用,通过clone克隆出一个对象,然后由工厂分配给调用者
结构模式
特点:是从程序的结构上实现松耦合,从而扩大整体的类结构,用来解决更大的问题
代理模式
核心作用:
1:通过代理,控制对对象的访问
2:可以详细控制访问某个(某类)对象的方法,调用这个方法之前做前置处理,调用这个方法之后做后置处理
应用场景:
1:安全代理—屏蔽对真实角色的直接访问
2:远程代理—通过代理角色来处理远程方法调用(RMI)
3:延迟加载—先加载轻量级的代理对象,真正需要的时候再加载真实的对象下
代理模式是AOP(面向切面编程)的核心实现机制
在代理类的前面以及后面加上不同的切面就形成了面向切面编程
注:
面向切面编程:它是可以通过预编译方式以及运行期动态代理的方式实现在不修改源代码的情况下给程序动态统一添加功能的一种技术
切面:将相似重复的代码抽离出来,形成一个切面。然后在动态代理的时候,前后添加不同的切面进行相应的处理
核心角色:
抽象角色:定义代理角色,和真实角色的公共对外方法
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用,这个真实角色关注的时候真实的业务逻辑
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑,来实现抽象方法,并可以附加自己的操作。统一的流程控制是放在代理角色中实现的
代理模式分为两大类
静态代理
静态生成代理对象,程序员手动或者工具创建的代理类,在程序运行之前已经就存在代理类的字节码文件,代理类与委托类在程序运行之前就已经确定下来了的称之为静态代理
实现:
以明星约明星唱歌的全流程为例,除了唱歌,面谈,订机票之类活动就没必要让明星自己来。这些可以让经纪公司(代理对象)来处理
a):定义抽象角色
public interface Star {
//面谈
void confer();
//签合同
void signContract();
//订机票
void bookTicket();
//唱歌
void sing();
//收尾款
void collecMoney();
}
b):定义真实角色(明星类)
public class realStar implements Star {
@Override
public void confer() {
System.out.println("面谈");
}
@Override
public void signContract() {
System.out.println("签合同");
}
@Override
public void bookTicket() {
System.out.println("订飞机票");
}
@Override
public void sing() {
System.out.println("周杰伦唱歌");
}
@Override
public void collecMoney() {
System.out.println("收尾款");
}
}
c):创建代理角色
public class ProxyStar implements Star {
private Star star;
public ProxyStar(Star star) {
this.star = star;
}
@Override
public void confer() {
System.out.println("代理面谈");
}
@Override
public void signContract() {
System.out.println("代理签合同");
}
@Override
public void bookTicket() {
System.out.println("代理订机票");
}
@Override
public void sing() {
star.sing();
}
@Override
public void collecMoney() {
System.out.println("代理收尾款");
}
}
代理对象持有真实角色的引用,真实业务方法,可以直接调用真实角色的方法。除此之外,都是代理对象的方法在发挥作用
优点:
而业务类只需要关注于业务逻辑本身就好了
缺点:
1:静态代理的一个接口只服务于一个对象,该对象的方法越多,那么需要代理的方法也就越多,在程序规模稍大一些,静态代理就应付不过来了。
2:如果接口新增一个方法,不仅实现类需要实现该方法,代理类也需要实现该方法,不利于程序后期维护。
动态代理
动态代理类是在JVM在程序运行的时候,根据反射机制动态生成的。所以不存在代理类的源文件。
实现:
a+b步骤与静态代理一致,这里就不重复写了
c):生成代理对象
动态代理对象需要实现InvocationHandler接口
public class starHandler implements InvocationHandler {
Star star;
public starHandler(Star star) {
this.star = star;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
System.out.println("真的方法调用前");
System.out.println("面谈,签合同,预付款,订机票");
if(method.getName().equals("sing")){
invoke = method.invoke(star, args);
}
System.out.println("付尾款");
System.out.println(method.getName());
return invoke;
}
}
InvocationHandler接口,是代理调用器的接口,其中定义了一个方法–invoke.
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
这个方法的第一个参数是代理类实例。第二个参数是调用的方法,第三个参数是调用方法传过来的参数
b):客户端调用代理对象
public class Client {
public static void main(String[] args) {
//创建一个真实角色
realStar realStar = new realStar();
//将真实角色传递给代理处理器中
starHandler starHandler = new starHandler(realStar);
//由Proxy生成代理对象类
Star invocationHandler = (Star) Proxy.newProxyInstance(
ClassLoader.getSystemClassLoader(),
new Class[]{Star.class}, starHandler);
invocationHandler.sing();
}
}
Proxy是所有动态代理的父类
newProxyInstance是创建动态代理的方法
第一个参数是类装载器,用于类的字节码文件装载进JVM(java虚拟机)中生成类对象。这个类对象与一般类的区别在于,是程序运行时,由JVM动态的生成,而不预先存在于任何一个class文件中。动态代理类就是由这个类装载器进行装载生成。
第二个参数是代理类接口(一般与真实角色的接口一致),目的在于能够调用与真实角色一样的方法。利用反射机制,得到动态代理类的构造函数
第三个参数是代理处理器对象,利用构造函数,创造出动态代理类
享元模式
特点:
1;享元模式以共享的方式高效的支持大量细粒度对象的重用
2:享元模式能够做到共享的关键是在于区分了内部状态以及外部状态
注:
1):内部状态:可以共享,不会随着环境变化而变化
2):外部状态:不可以共享,会随着环境变化而变化
应用场景:
1:内存属于稀缺资源,如果有很多相似或相同的对象,可以通过享元模式,进行节省内存。比如说,一个实体会被实例化出对象多个,而这多个对象有一部分属性或者功能是一致的,不会因为外部条件的改变而改变。那么种情况下,就可以使用享元模式,把共有的部分进行共享,减少内存的占用。
2:享元模式由于其共享的特性,可以在任何”池“中操作,比如线程池,数据库连接池等
优点:
1:极大的减少了内存中对象的数量
2:相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
3:外部状态相对独立,不影响内部状态
缺点:
1:模式较复杂,是程序逻辑复杂化
2:为了节省内存,共享了内部状态,分理出外部状态,而读取外部状态,使运行时间变长,用时间换取了空间、
实现(以围棋为例,围棋的颜色,大小等不会变,可以作为内部状态进行共享。变得是围棋的位置,这个单独抽离出来,作为对象的外部状态):
创建享元抽象类
(用来定义内部状态的方法(不容易变得部分),以及可以设置外部状态的方法(容易变·的部分))
public interface ChessFlyWeight {
void setColor(String color);
String getColor();
void display(Coordinate c);
}
创建享元具体类:
class chessConcrete implements ChessFlyWeight{
private String color;
@Override
public void setColor(String color) {
}
public chessConcrete(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
//设置外部状态的地方
@Override
public void display(Coordinate c) {
System.out.println("棋子颜色:"+color);
System.out.println("棋子位置:"+c.getX()+"---"+c.getY());
}
}
创建非享元具体类(外部状态:围棋的位置)
public class Coordinate {
private int x,y;
public int getX() {
return x;
}
public int getY() {
return y;
}
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
}
创建享元工厂类:
public class chessFlyWeightFactory {
private static HashMap<String,ChessFlyWeight> map=new HashMap<String,ChessFlyWeight>();
public static ChessFlyWeight getFlyWeight(String color){
ChessFlyWeight chessFlyWeight=null;
if (map.get(color)!=null){
chessFlyWeight=map.get(color);
}else {
chessFlyWeight = new chessConcrete(color);
map.put(color,chessFlyWeight);
}
return chessFlyWeight;
}
}
内部置放一个map,用对象固定不变的部分作为键,对象本身作为值进行传入。保证每一个相同或者相似的对象都是同一个。在工厂产出的对象中,再给其传入外部的特征。
装饰模式
特点:
1:动态的为一个对象增加新的功能
2:装饰模式,是一种替代继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系替换继承关系,更加灵活,同时避免类型体系快速膨胀
优点:
1:扩展对象功能比继承更加灵活,不会导致类个数急剧增加
2:可以对一个对象进行多次的装饰,创造出不同行为的组合,得到功能更强大的对象
缺点:
1:会产生很多小对象,大量小对象占据内存,一定程度上影响性能
2:装饰模式易于出错,错误排查比较麻烦
重要角色:
1:Component抽象构件角色:真实对象与装饰对象都有相同的接口,这样客户端就可以对真实对象那样与装饰对象进行交互
2:ConcreteComponent具体构件角色(真实对象):实现核心业务方法的对象
3:Decorator装饰角色:持有装饰对象的引用,装饰对象接受客户端所有的请求,并把这些请求转发给真实角色。这样就能在真实对象前后增加新的功能
4:ContreteDecorator具体装饰角色:负责给构件对象增加新的责任
实现:(以给汽车增加飞以及水里游两种功能为例)
创建抽象构建角色:
public interface ICar {
void move();
}
创建具体构件角色:‘’
class Car implements ICar{
@Override
public void move() {
System.out.println("陆地上跑");
}
}
创建装饰角色1:
class FlyCar extends SuperCar{
public FlyCar(ICar iCar) {
super(iCar);
}
public void Fly(){
System.out.println("天上飞");
}
@Override
public void move() {
super.move();
Fly();
}
}
创建装饰角色2:
class WaterCar extends SuperCar{
public WaterCar(ICar iCar) {
super(iCar);
}
public void swin(){
System.out.println("水里游");
}
@Override
public void move() {
super.move();
swin();
}
}
创建客户端进行调用:
public class Client {
public static void main(String[] args) {
Car car = new Car();
FlyCar flyCar = new FlyCar(car);
WaterCar waterCar = new WaterCar(flyCar);
System.out.println("---");
waterCar.move();
}
}
装饰器模式可以降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体装饰类(装饰对象),和具体构件类(真实对象)可以独立的变化,以便可以增加新的构件类和具体装饰类
适配器模式
特点:将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以在一起工作
适配器模式类似于现实中的转接线,将PS/2接口转换为常用的USB接口,将原有对象不兼容的接口,转换为兼容的接口
模式中的角色
目标接口:客户所期望的接口,目标可以时具体的以及抽象的类,也可以是接口
需要适配的类:需要将不适配的接口,转换为适配接口的类
适配器:通过包装一个需要适配的对象,把原接口转换成目标接口
实现(以ps/2接口的键盘通过适配器转成USB(Target)接口为例):
创建需要适配的类
public class Adaptee {
public void request(){
System.out.println("可以打字");
}
}
创建目标接口
public interface Target {
void handler();
}
目标接口的目的在于调用被适配类的功能实现
创建适配器
适配器的分类为两种:
第一种:类适配器
public class Adapter extends Adaptee implements Target{
@Override
public void handler(Adaptee a) {
a.request();
}
}
第二种:组合对象适配器
public class Adapter implements Target{
Adaptee a=null;
@Override
public void handler() {
a.request();
}
public Adaptee getA() {
return a;
}
public void setA(Adaptee a) {
this.a = a;
}
}
类适配器与组合对象适配器的区别:
类适配器不够灵活,因为继承只能继承一个。而组合对象,能够适配多个不同类型的类
桥接模式
特点:
1:桥接模式可以替代多层继承的结构,多层继承违背了单一职责的原则,复用性较差,类的个数也是比较多。桥接模式极大的降低了类的个数,从而降低管理和维护的成本
2:桥接模式极大的提高了系统可扩展性,在多个变化维度中任意扩展一个维度,都不需要修改原有系统,符合开闭原则
应用场景·:一个类可能会因为两个维度以上的原因发生变化的时候,就可以考虑桥接模式了。在处理多层继承结构, 多维度变化的场景中,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关系(比如一台电脑会因为电脑品牌以及电脑种类得不同而不同。在传统代码结构上,需要新增加一个电脑得品牌或者电脑种类,那么相应需要添加得具体实现类比较多。在桥接模式下,可以将电脑品牌与电脑种类这两个维度,生成两个独立的继承结构,当需要的时候,再相互组合。当发生单个维度上得扩展时,只需要对该维度进行相应的操作与修改,不会影响到其他维度得变化。)
实现:
创建品牌维度得接口:
public interface Brand {
void sale();
}
创建品牌维度得具体实现类
实现类1
class lenovo implements Brand {
@Override
public void sale() {
System.out.println("销售联想电脑");
}
}
实现类2
class Dell implements Brand {
@Override
public void sale() {
System.out.println("销售戴尔电脑");
}
}
创建电脑种类维度的抽象类
public abstract class Computer1 {
protected Brand brand;
public Computer1(Brand brand) {
this.brand = brand;
}
public void sale(){
brand.sale();
}
}
创建电脑种类得具体实现类
实现类1:
class Desktop2 extends Computer1{
@Override
public void sale() {
System.out.println("销售台式机");
super.sale();
}
public Desktop2(Brand brand) {
super(brand);
}
}
实现类2
class Laptop1 extends Computer1{
@Override
public void sale() {
System.out.println("销售笔记本");
super.sale();
}
public Laptop1(Brand brand) {
super(brand);
}
}
创建客户端
public class Client {
public static void main(String[] args) {
lenovo lenovo = new lenovo();
Desktop2 desktop2 = new Desktop2(lenovo);
desktop2.sale();
}
}
这就完成了两个维度得组合调用
组合模式
特点:把整体和部分的关系用树形结构来表示,从而使客户端可以使用统一的方式处理部分对象和整体对象
核心角色:
抽象构件角色:定义了叶子和容器构件的共同点
**叶子构件角色:**无子节点
容器构件角色:有容器特征,可以包含子节点
工作流程:
1:使用组合模式处理树状结构的时候,天然具有递归的特性。使得用户在使用时可以一致性的方法对待容器和叶子
2:当容器对象的方法调用,将遍历整个树形结构,寻找包含这个方法的成员,并调用执行,其中使用了递归调用的机制,对整个结构进行处理
实现(以给文件杀毒为例,文件存放于一个树状结构的容器里):
创建抽象构件角色:
public interface AbstractFile {
void killVirus();
}
给叶子与容器定义了统一的killVirus(杀毒)方法
创建叶子构件角色:
class ImageFile implements AbstractFile{
String name;
public ImageFile(String name) {
this.name = name;
}
@Override
public void killVirus() {
System.out.println("图像文件"+name+"进行查杀");
}
}
创建容器构件角色
class Folder implements AbstractFile {
private String name;
ArrayList<AbstractFile> list =new ArrayList<AbstractFile>();
public Folder(String name) {
this.name = name;
}
public void add(AbstractFile a){
list.add(a);
}
public void remove(AbstractFile a){
list.remove(a);
}
public AbstractFile getChild(int a){
AbstractFile abstractFile = list.get(a);
return abstractFile;
}
@Override
public void killVirus() {
System.out.println("文件夹:"+name+"进行查杀");
for (int i =0 ;i<list.size();i++){
list.get(i).killVirus();
}
}
}
容器与叶子都继承了抽象构件的方法,在客户端,只需要使用一个方法,就可以对叶子进行相应的操作,也可以对容器进行操作。由于方法都是一致的(容器内的方法需要做循环处理),所以天然具备递归的特性
外观模式
这个模式遵从迪米特法则
注:
迪米特法则:一个对象应该对其他对象尽可能地少的知道
法则得由来:类与类之间得耦合度越高,当一个类发生变化,对于其他与之具有耦合度的类就有比较大的影响。
解决方案:降低类与类之间的耦合度
核心:为子系统提供统一的入口,封装子系统的复杂性,便于客户端调用
核心角色:
外观角色:对外提供了一个可以访问内部系统的接口,对内封装了各个子系统的细节。
子系统角色:在系统中一个或者多个模块,每一个模块中有多个类,多个类之间也许存在多个
实现:
创建子系统模块
public class ClassA {
public void methodA(){
System.out.println("methodA方法开始执行");
}
}
public class ClassB {
private ClassA classA;
public ClassB(ClassA classA) {
this.classA = classA;
}
public void methodB(){
classA.methodA();
System.out.println("methodB方法开始执行");
}
}
public class ClassC {
private ClassB classB;
public ClassC(ClassB classB) {
this.classB = classB;
}
public void methodC(){
classB.methodB();
System.out.println("methodC方法开始执行");
}
}
public class Facade {
private ClassA classA=new ClassA();
private ClassB classB =new ClassB(classA);
private ClassC classC =new ClassC(classB);
public void test(){
classC.methodC();
classA.methodA();
classB.methodB();
}
}
创建外观角色
public class Facade {
private ClassA classA=new ClassA();
private ClassB classB =new ClassB(classA);
private ClassC classC =new ClassC(classB);
public void test(){
classC.methodC();
classA.methodA();
classB.methodB();
}
}
创建客户端进行调用
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.test();
}
}
在这里,对于客户端,ClassA,ClassB,ClassC都是隐藏得,只需要调用Facade(外观角色),就好了。
行为型模式
特点:行为型模式关注的系统中对象之间的相互交互,研究系统在运行时对对象之间相互通信与协作,进一步明确对象的职责
命令模式
特点:将一个请求封装为一个对象,从而可以使不同的请求,日志,队列对其他对象进行参数化,支持可撤销操作
比如将控制电视换台,调整音量等命令,等封装到遥控器上,这就实现了调用者与执行者得解耦合,不用每次对电视的操作都需要走到电视面前对电视本身进行操作。
实现:
创建执行者:
接收者z执行与请求相关的操作,具体实现对请求的业务处理
public class Receiver {
public void action(){
System.out.println("执行者开始执行命令");
}
}
创建命令对象接口
public interface Command {
void execute();
}
创建命令对象具体实现类
class ConcreteCommand implements Command{
private Receiver receiver;//命令的真正的执行者
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//此处,命令执行前后,可以做相应的操作
receiver.action();
}
}
创建请求的发送者
请求的发送者,它通过命令对象来执行请求,一个调用者,并不需要在设计的时候,q确定其接收者,因此它z只与抽象命令类之间存在关联。在程序运行时,将调用命令对象execute(),间接调用接收者的相关操作
public class Invoke {
private Command command;//可以通过list<Command>容纳很多命令对象可以进行命令的批处理
public Invoke(Command command) {
this.command = command;
}
//业务方法,用于调用命令类的方法
public void call(){
command.execute();
}
}
迭代器模式
特点:
1:提供一种可以遍历聚合对象的方式,又称为:游标cursor模式(游标移到哪里,才能获取到哪里的对象,游标只能向一个方向按顺序进行移动)
2:迭代器提供了一个接口,可以访问容器内部的数据,而不需要用户明白容器内部得数据结构。实现了数据结构,与操作数据结构的算法进行分离。
注:
聚合对象:也可以理解为储存了一堆的对象得对象
迭代器:遍历数据
平时项目中用不到,主要是为了熟悉这种模式
实现:
创建迭代器接口:
public interface Myiterator {
void first();//将游标指向第一个
void next();//将游标指向一下
boolean hasNext();//判断是都存在下一个
boolean isFirst();//判断当前游标指向的对象是否是第一个对象
boolean isLast();//判断当前游标指向的对象是否是最后一个对象
Object getCurentObj();//获取当前游标指向的对象
}
创建具体迭代器对象
ConcreateIterator是内部类,之所以是创建成内部类,是因为内部类可以直接调用父类的方法和属性
这个类主要是模拟迭代器各个方法实现
public class ConcreateMyAggragate {
private ArrayList<Object> list=new ArrayList<Object>() ;
public ConcreateMyAggragate() {
this.list = list;
}
public void addObject(Object o){
this.list.add(o);
}
public void removeObject(Object o){
this.list.remove(o);
}
public ArrayList<Object> getList() {
return list;
}
public void setList(ArrayList<Object> list) {
this.list = list;
}
public Myiterator createIterator(){
return new ConcreteIterator();
}
private class ConcreteIterator implements Myiterator{
private int cursor;
@Override
public void first() {
cursor=0;
}
@Override
public void next() {
if (cursor<=list.size()){
cursor++;
}
}
@Override
public boolean hasNext() {
return cursor<list.size()-1;
}
@Override
public boolean isFirst() {
return cursor==0;
}
@Override
public boolean isLast() {
return cursor==list.size()-1;
}
@Override
public Object getCurentObj() {
return list.get(cursor);
}
}
}
中介者模式
特点: 解耦多个同事对象之间的交互关系,每个对象都持有中介者对象的引用,只跟中介者对象打交道。
核心:
1:如果一个系统中对象之间的联系呈现为网状结构,对象之间存在大量的多对多的情况,将导致关系变得非常复杂,这些对象称之为”同事对象“
2:引入中介者对象,使各个同事对象只跟中介者打交道,将复杂的网络结构化解为星状结构
实现(以不同部门通过总经理调度资源为例)
创建同事对象接口类
public interface Department {
void selfAction();//本部门需要做的事情
void outAction();//需要其他部门协助的事情
}
创建同事对象具体实现类1
public class Development implements Department {
private Mediator m;//持有中介者(总经理)的引用
public Development(Mediator m) {
this.m = m;
m.register("Development",this);
}
@Override
public void selfAction() {
System.out.println("专心科研,开发项目");
}
@Override
public void outAction() {
System.out.println("汇报工作,没钱了,需要资金支持");
m.command("finacial");//通过总经理调用其他部门的能力
}
}
创建同事对象具体实现类2
public class Finacial implements Department {
private Mediator m;//持有中介者(总经理)的引用
public Finacial(Mediator m) {
this.m = m;
m.register("finacial",this);
}
@Override
public void selfAction() {
System.out.println("数钱");
}
@Override
public void outAction() {
System.out.println("汇报工作。怎么花钱");
}
}
创建中介者接口类
public interface Mediator {
void register(String dname,Department d);//key是部门名称,value是部门对象
void command(String dname);//根据部门名称调用某个部门的功能
}
创建中介者具体实现类(总经理)
public class president implements Mediator {
private Map<String ,Department> map=new HashMap<>();
@Override
public void register(String dname, Department d) {
map.put(dname,d);
}
@Override
public void command(String dname) {
map.get(dname).selfAction();
}
}
创建客户端
public class Client {
public static void main(String[] args) {
president president = new president();
Finacial finacial = new Finacial(president);
Development development = new Development(president);
development.outAction();
}
}
责任链模式
特点:将能够处理同一类请求的对象连成一条链,所提交的请求沿着链进行传递,链上的对象逐个判断是否有能力处理该请求,如果能处理,不行就传递给链上的下一个对象。
优点:相对于if–else判断,更加符合开闭原则。该链上每增加一个处理对象,不需要修改原有系统中的代码,只需要创建出该类型的对象,指定在该责任链上的位置就好了.
实现:(以不同层次的领导处理请假条为例)
创建请求实体类
public class LeaveRequest {
//请假人姓名
private String empName;
//请假时间
private int leaveDays;
//请假理由
private String reson;
public LeaveRequest(String empName, int leaveDays, String reson) {
this.empName = empName;
this.leaveDays = leaveDays;
this.reson = reson;
}
public String getReson() {
return reson;
}
public String getEmpName() {
return empName;
}
public int getLeaveDays() {
return leaveDays;
}
}
创建责任链上各节点得抽象实体类
public abstract class Leader {
protected String name;
//传入下一个处理者的引用,如果该处理者处理不了,好将该请求传递给下一个处理者
protected Leader nexLeader;
public Leader(String name) {
this.name = name;
}
public void setNexLeader(Leader nexLeader) {
this.nexLeader = nexLeader;
}
//该处理者的处理方法
public abstract void requestHandler(LeaveRequest leaveRequest);
}
创建责任链上得节点具体实体类1
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void requestHandler(LeaveRequest leaveRequest) {
if(leaveRequest.getLeaveDays()<3){
System.out.println(leaveRequest.getLeaveDays()+"---"+leaveRequest.getEmpName());
System.out.println("主任给批了");
}else {
if(nexLeader!=null){
nexLeader.requestHandler(leaveRequest);
}else {
System.out.println("拒接批准请假");
}
}
}
}
创建责任链上得节点具体实体类2
public class Manage extends Leader {
public Manage(String name) {
super(name);
}
@Override
public void requestHandler(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays()<10){
System.out.println(leaveRequest.getLeaveDays()+"---"+leaveRequest.getEmpName());
System.out.println("经理批了");
}else {
if(nexLeader!=null){
nexLeader.requestHandler(leaveRequest);
}else {
System.out.println("拒接批准请假");
}
}
}
}
创建责任链上得节点具体实体类3
public class GeneralManager extends Leader {
@Override
public void requestHandler(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays()<30){
System.out.println(leaveRequest.getLeaveDays()+"---"+leaveRequest.getEmpName());
System.out.println("总经理批了");
}else {
if(nexLeader!=null){
nexLeader.requestHandler(leaveRequest);
}else {
System.out.println("拒接批准请假");
}
}
}
public GeneralManager(String name) {
super(name);
}
}
public class Client {
public static void main(String[] args) {
LeaveRequest leaveRequest = new LeaveRequest("张三", 31, "世界那么大,我想去给看看");
Director lisi = new Director("李四");
Manage wangwu = new Manage("王五");
GeneralManager zhaoliu = new GeneralManager("赵六");
lisi.setNexLeader(wangwu);
wangwu.setNexLeader(zhaoliu);
lisi.requestHandler(leaveRequest);
}
}
这个例子展示的是在责任链中,请求在各节点对象中传递的步骤演示。责任链不仅可以在链上找对应的对象对该请求做相应的处理。而且,链上的不同的对象也可以对该请求做不同的处理。比如说OkHttp,HttpClient处理请求,我们只需要将参数传入就好了,其中是不带请求头的,如果Http框架使用的责任链模式,可能第一个责任链上的节点的功能是给该请求添加请求头,然后封装成请求1,如果需要该请求的本地缓存的话,那么第二个节点可以给该请求做缓存处理,然后封装成请求2。
策略模式
特点:策略模式对应于解决某一个问题的算法族,允许用户从该算法族中任选一个算法解决某一个问题,同时可以方便的更换算法或者增加新的算法,并且由客户端决定·调用哪一个算法
优点:可以动态得改变对象得行为(自由的选择算法,而不同的算法决定对象不同的行为)
缺点:
1:客户端必须知道所有得策略类,并自行决定哪一个策略类
2:策略模式产生很多得策略类
重要对象:
环境对象:用一个ConstreteStrategy对象配置,维护一个对Strategy对象得引用,可定义一个接口来让Strategy访问它的数据
抽象策略类:定义所有支持得算法的接口,Context使用这个接口来调用某ContreteStrategy定义的算法
具体策略类:以Strategy为接口实现得具体实现算法
实现(以不层次的客户购买商品为例)
创建抽象策略类
public interface Strategy {
public double getPrice(double standerdPrice);
}
创建具体策略类1
public class newConstumerFewStrategy implements Strategy{
@Override
public double getPrice(double standerdPrice) {
System.out.println("普通客户小批量,不打折");
return standerdPrice;
}
}
创建具体策略类2
public class newConstumerManyStrategy implements Strategy{
@Override
public double getPrice(double standerdPrice) {
System.out.println("普通客户大批量,打九折");
return standerdPrice * 0.9;
}
}
创建具体策略类3
public class oldConstumerFewStrategy implements Strategy{
@Override
public double getPrice(double standerdPrice) {
System.out.println("老客户小批量,打八五折");
return standerdPrice * 0.85;
}
}
创建具体策略类4
public class oldConstumerManyStrategy implements Strategy{
@Override
public double getPrice(double standerdPrice) {
System.out.println("老客户小批量,打八折");
return standerdPrice * 0.8;
}
}
状态模式
特点:用于解决复杂对象中状态的切换,以及不同的状态中不同的行为得封装的问题
一个对象的行为受一个或者多个属性影响,这样的属性叫做状态,这样的对象也叫做有状态的对象。这样的对象于外界环境进行交互的时候,内部的状态也会发生变化,对象的行为也就随之发生变化。
应用场景:
当一个对象行为取决于自身的状态的时候(比如做菜有几种状态:1:买菜,2:洗菜,3:炒菜,不同的状态有不同的行为)
重要对象:
1:环境对象:持有一个具体状态对象实例,这个实例定义了当前对象的状态
2:抽象状态类:定义一个接口与一个环境对象特定状态相关的行为
3:具体状态类:抽象状态抽象状态类的子类,是对象的各个状态
实现:
创建环境对象:
public class Context {
//持有一个具体具体状态类对象的实例,每次持有一个新的状态,就调用这个状态对应的行为
private State state;
public void setState(State state){
System.out.println("修改状态");
this.state=state;
state.handle();
}
}
创建抽象状态类:
public interface State {
//定义具体状态类的行为
void handle();
}
创建具体状态类1:
public class FreeState implements State {
@Override
public void handle() {
System.out.println("房间空闲");
}
}
创建具体状态类2:
public class BookedState implements State {
@Override
public void handle() {
System.out.println("房间已经被预定了");
}
}
创建具体状态类3
public class CheckedInState implements State {
@Override
public void handle() {
System.out.println("房间已经入住");
}
}
创建客户端:
public class Client {
public static void main(String[] args) {
Context context = new Context();
FreeState freeState = new FreeState();
context.setState(new CheckedInState());
}
}
备忘录模式
特点:在不破坏对象封装性的前提下,捕获该对象的内部特征,并在该对象之外进行保存,以便以后可以对该对象进行恢复
就是保存某个对象内部状态的拷贝,这样就可以将该对象恢复到原先得状态
重要角色:
源发器:普通类,可以创建备忘录,也可以根据备忘录恢复状态
备忘录:储存源发器的内部状态,处理原发类与负责人类,不直接与其它类交互
负责人:保存备忘录,但是不操作和检查备忘录
实现:
创建源发器:
public class Emp {
private String ename;
private int age;
private double salary;
//进行备忘录操作,并返回备忘录对象
public EmpMemeto memeto() throws CloneNotSupportedException {
return new EmpMemeto(this);
}
public void recovery(EmpMemeto empMemeto){
this.ename=empMemeto.getEname();
this.age=empMemeto.getAge();
this.salary=empMemeto.getSalary();
}
public Emp(String ename, int age, double salary) {
this.ename = ename;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "Emp{" +
"ename='" + ename + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
创建备忘录对象:
属性与源发器对象一致,为了能保存源发器全部的内部特征–属性或者其他特征
public class EmpMemeto {
private String ename;
private int age;
private double salary;
public EmpMemeto(Emp e) {
this.ename=e.getEname();
this.salary=e.getSalary();
this.age=e.getAge();
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
创建负责人对象:
持有备忘录实例,可以是单个,也可以是一个列表的实例。当需要的时候,可以从这个负责人对象中拿出备忘录实例进行恢复
public class CareTaker {
private EmpMemeto empMemeto;
public EmpMemeto getEmpMemeto() {
return empMemeto;
}
public void setEmpMemeto(EmpMemeto empMemeto) {
this.empMemeto = empMemeto;
}
}
创建客户端
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
CareTaker careTaker = new CareTaker();
Emp zs = new Emp("张三", 21, 998);
EmpMemeto memeto = zs.memeto();
careTaker.setEmpMemeto(memeto);
zs.setAge(23);
zs.setEname("李四");
zs.setSalary(1998);
System.out.println(zs);
zs.recovery(careTaker.getEmpMemeto());
System.out.println(zs);
}
}
观察者模式
特点:定义了一对多的关系,多者对象同时监听同一个主题对象,当这个主题对象发生改变的时候,会通知订阅了该主题对象的监听者,使他们能够自动的更新自己
重要角色:
抽象主题类:抽象主题角色提供一个集合,可以保存任意个数的观察者。并且提供一个接口,可以增加和删除观察者具体主题类
具体主题类:该角色有关状态存入具体观察者对象,再具体主题对象内部状态发生变得时候,通知所有注册过的观察者。
抽象观察者:是观察者得抽象类,定义了一个更新的接口,使得得到主题对象更新通知时更新自己
具体观察者:实现抽象观察者定义的接口
实现:
创建抽象主题类
public interface Subject {
void register(Observer observer);
void remove(Observer observer);
void getObject(int index);
//通知所有观察者更新状态
void notifyAllObserver();
}
创建具体主题类
public class ConcreteSubject implements Subject {
private List<Observer> list=new ArrayList<Observer>();
public void register(Observer observer){
System.out.println("开始添加订阅者");
list.add(observer);
}
public void remove(Observer observer){
list.remove(observer);
}
public void getObject(int index){
list.get(index);
}
//通知所有观察者更新状态
public void notifyAllObserver(){
System.out.println("开始通知订阅者");
for (Observer obs: list
) {
obs.update(this);
}
}
//设置具体主题得内部状态
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//一旦内部状态发生改变,就通知所有订阅了该主题得监听者们
this.notifyAllObserver();
}
}
创建抽象观察者:
public interface Observer {
void update(Subject subject );
}
创建具体观察者:
public class ObjacctA implements Observer{
private int myState;
@Override
public void update(Subject subject) {
myState = ((ConcreteSubject) subject).getState();
System.out.println("状态改变了:"+myState);
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
创建客户端:
public class Client {
public static void main(String[] args) {
//目标主题对象
ConcreteSubject concreteSubject = new ConcreteSubject();
ObjacctA objacctA = new ObjacctA();
concreteSubject.register(objacctA);
System.out.println("===");
concreteSubject.setState(2);
}
}
模板方法模式
特点:模板方法模式是编程中经常用得模式,它定义了一个操作中得算法骨架,将某些步骤,延迟到子类中实现,这样的,新的子类可以在不改变算法结构的情况下,重新定义该算法的某些特定的步骤
优点:
1:封装不变的部分,扩展可变的部分
2:提取公共代码,便于维护
3:行为有父类控制,子类实现
重要角色:
1:抽象角色:定义了一个算法的轮廓以及骨架,它是由一个模板方法,以及若干个基本方法组成
①:模板方法:定义了算法的骨架,包含了按照某种顺序调用的基本方法
②:基本方法:是整个算法的一个步骤,包含以下几种类型
a):抽象方法:在抽象类中申明,由子类去实现
b):具体方法:在抽象类中已经实现,在子类中继承或者重写
c):钩子方法:包括判断的逻辑方法,以及需要子类重写的空方法两种
2:具体子类:实现抽象类中的抽象方法以及钩子方法,他们是一个顶级逻辑的组成部分
实现
创建抽象类
public abstract class BankTemplateMethod {
public void takebNumber(){
System.out.println("取号排队");
}
public abstract void transact();//办理具体的业务
public void evaluate(){
System.out.println("反馈评分");
}
//模板方法
public final void process(){
//具体方法
takebNumber();
//钩子方法
transact();
//具体方法
evaluate();
}
}
创建具体子类:
class DrawMoney extends BankTemplateMethod{
@Override
public void transact() {
System.out.println("取钱");
}
}
创建客户端:
public class Client {
public static void main(String[] args) {
BankTemplateMethod drawMoney = new DrawMoney();
drawMoney.process();
}
}
解释器模式
特点:一般用于创造新语言的时候,类似于易语言,运行的过程中是将中文,解释成C语言,然后再由C语言进行编译运行。
实现:
创建解释器接口
public interface AbstractExpression {
void explain();
}
创建解释器
public class Expression1 implements AbstractExpression {
@Override
public void explain() {
System.out.println("for");
}
}
创建客户端
public class Client {
public static void main(String[] args) {
String java="for(;;){}";
if(java.equals("for(;;){}")){
Expression1 expression1 = new Expression1();
expression1.explain();
}
}
}
这是将Java的for语句转换为python的for语句