大话设计模式(终)

Java的设计模式三大类

1.中介者模式(Mediator)

中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行,这有点像spring容器的作用。

User接口:

public abstract class User {
   private Mediator mediator;

   public Mediator getMediator() {
       return mediator;
   }

   public User(Mediator mediator) {

       this.mediator = mediator;
   }
   public abstract void work();

}

User1:

public class User1 extends User {
   public User1(Mediator mediator) {
       super(mediator);
   }

   @Override
   public void work() {
       System.out.println("user1 exe....");
   }
}

User2:

public class User2 extends User {
   public User2(Mediator mediator) {
       super(mediator);
   }

   @Override
   public void work() {
       System.out.println("user2 exe....");
   }
}

中介接口:

public interface Mediator {
   public void creatMediator();
   public void allWorkers();
}

中介实现:

public class myMediator implements Mediator{
   private User1 user1;
   private User2 user2;

   public User2 getUser2() {
       return user2;
   }

   public User1 getUser1() {

       return user1;
   }

   @Override
   public void creatMediator() {
       user1=new User1(this);
       user2=new User2(this);
   }

   @Override
   public void allWorkers() {
       user1.work();
       user2.work();
   }
}

测试:

public class Test {
   public static void main(String[] args){
       Mediator mediator=new myMediator();
       mediator.creatMediator();
       mediator.allWorkers();
   }
}

 结果:

类图如下:

2.解释器模式(Interpreter Pattern)

解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄。

上下文环境类:

public class Context {
   private int num1;
   private int num2;

   public Context(int num1,int num2) {
       this.num1 = num1;
       this.num2 = num2;
   }

   public int getNum2() {
       return num2;
   }

   public void setNum2(int num2) {
       this.num2 = num2;
   }

   public int getNum1() {

       return num1;
   }

   public void setNum1(int num1) {
       this.num1 = num1;
   }
}

计算接口:

public interface Expression {
   public int expression(Context context);
}

实现类:

public class Plus implements Expression{
   @Override
   public int expression(Context context) {
       return context.getNum1()+context.getNum2();
   }
}
public class Minus implements Expression{
   @Override
   public int expression(Context context) {
       return context.getNum1()-context.getNum2();
   }
}

测试:

public class Test {
   public static void main(String[] args){
       //21+22-2
       int result=new Minus().expression(new Context(new Plus().expression(new Context(21,22)),2));
       System.out.println(result);
   }
}

结果:41

类图如下:



3.备忘录模式(Memento)

主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫备份模式更形象些,通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。

原始类A:

public class A {
   private String Value;
   private B b;

   public A(String value) {
       Value = value;
   }
   public String getValue() {
       return Value;
   }
   public void setValue(String value) {
       Value = value;
   }
   public B creatB(){
       return new B(Value);
   }
   public void restoreB(B b){
       this.Value=b.getValue();
   }

}

备忘录B:

public class B {
   private String value;
   public String getValue() {
       return value;
   }

   public void setValue(String value) {
       this.value = value;
   }

   public B(String value) {
       this.value = value;
   }
}

存储备忘录的类C:

public class C {
   private B b;

   public B getB() {
       return b;
   }

   public void setB(B b) {
       this.b = b;
   }

   public C(B b) {

       this.b = b;
   }
}

测试:

public class Test {
   public static void main(String[] args){
       //创建原始类
       A a=new A("water");
       //创建备忘录
      C c=new C(a.creatB());
       //修改原始类的状态
       a.setValue("ice");
       //恢复原始类的状态
       a.restoreB(c.getB());
   }
}

结果:


类图如下


4.享元模式(Flyweight)


我们就拿这幅画来说,里面画了草、树、路、山、天空等等。如果没有用享元模式,我们可能这样子实现。

蜡笔接口。

interface ICrayon {

    void draw(String place);

}

蜡笔。

// 蜡笔

class Crayon implements ICrayon {

    private String color;

    public Crayon(String color{
        System.out.println("---新建【" + color + "】蜡笔" );
        this.color = color;
    }

    @Override
    public void draw(String place
{
        System.out.println("用" + this.color + "蜡笔画" + place);
    }
}

测试代码。这幅画是小明和小红一起画,小明画了草和路,小红画了树和蓝天。

public class NoFlyweightTest {

    public static void main(String[] args) {
        drawByXiaoMing();
        drawByXiaoHong();
    }

    public static void drawByXiaoMing() {
        ICrayon greenCrayon = new Crayon("绿色");
        greenCrayon.draw("草");

        ICrayon grayCrayon = new Crayon("灰色");
        grayCrayon.draw("路");
    }

    public static void drawByXiaoHong() {
        ICrayon blueCrayon = new Crayon("蓝色");
        blueCrayon.draw("蓝天");

        ICrayon greenCrayon = new Crayon("绿色");
        greenCrayon.draw("树");
    }

}

打印结果:
---新建【绿色】蜡笔
用绿色蜡笔画草
---新建【灰色】蜡笔
用灰色蜡笔画路
---新建【蓝色】蜡笔
用蓝色蜡笔画蓝天
---新建【绿色】蜡笔
用绿色蜡笔画树

我们发现小明和小红都用了绿色蜡笔,而这里新建了 2 次绿色蜡笔,也就是在整个作画过程中,小明和小红并不是共用一套蜡笔,而是各自用一套蜡笔,在现实中是没什么问题的,但是在软件开发中,如果这种情况出现,其实相当于资源浪费,因为每个蜡笔都会占用内存,可以共用的我们尽量共用,节省一些内存空间,特别是出现很多这种可以共享却没有共享的对象时候。下面我们引入享元模式。享元模式实现方法相当于我们蜡笔都放在了笔袋,小明和小红用完就放到笔袋里面,每一种颜色的蜡笔只有一根,也就是他们共用一套蜡笔。代码如下所示。

笔袋代码。我们用了 Map 作为容器,如果容器里面没有想要颜色的蜡笔,则创建新的蜡笔,并存到容器里。

// 笔袋
class CrayonFactory {

    private static Map<String, ICrayon> data = new HashMap<>();

    public static ICrayon getCrayon(String color{
        if (data.containsKey(color)) {
            return data.get(color);
        }
        ICrayon crayon = new Crayon(color);
        data.put(color, crayon);
        return crayon;
    }

}

测试代码。

public class FlyweightTest {

    public static void main(String[] args) {
        drawByXiaoMing();
        drawByXiaoHong();
    }

    public static void drawByXiaoMing() {
        ICrayon greenCrayon = CrayonFactory.getCrayon("绿色");
        greenCrayon.draw("草");

        ICrayon grayCrayon = CrayonFactory.getCrayon("灰色");
        grayCrayon.draw("路");
    }

    public static void drawByXiaoHong() {
        ICrayon blueCrayon = CrayonFactory.getCrayon("蓝色");
        blueCrayon.draw("蓝天");

        ICrayon greenCrayon = CrayonFactory.getCrayon("绿色");
        greenCrayon.draw("树");
    }
}

打印结果:
---新建【绿色】蜡笔
用绿色蜡笔画草
---新建【灰色】蜡笔
用灰色蜡笔画路
---新建【蓝色】蜡笔
用蓝色蜡笔画蓝天
用绿色蜡笔画树

利用享元模式实现的结果,小红画树所用到的绿色蜡笔跟小明画草的绿色蜡笔一样,小红用到时并没有新建绿色蜡笔。

类图如下:




全部评论