分享

23种设计模式详解(二)

 太极混元天尊 2018-05-07


 



1.工厂方法模式FactoryMethod Pattern)

一、普通工厂方法模式

就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

举例:手机发短信或微信。

手机:


public interface Phone {
   public void send();
}


老年机:


public class oldMachine implements Phone{
   @Override
   public void send() {
       //老年机只能发短信
       System.out.println('发短信');

   }
}


智能机:


public class smartPhone implements Phone {
   @Override
   public void send() {
       //智能机可以发微信
       System.out.println('发微信');
   }
}


工厂:


public class Factory {
   public Phone send(String type){
       if('oldMachine'.equals(type)){
           return new oldMachine();
       }else if('smartPhone'.equals(type)){
           return new smartPhone();
       }
       return null;
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Factory factory=new Factory();
       Phone phone=factory.send('oldMachine');
       phone.send();
   }
}


结果:



二、多个工厂方法模式

是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

工厂:


public class Factory {
   public Phone sendMail(){
       return new oldMachine();
   }
   public Phone sendWechat(){
       return new smartPhone();
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Factory factory=new Factory();
       Phone phone=factory.sendMail();
       phone.send();
   }
}


结果:



三、静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

工厂:


public class Factory {
   public static Phone sendMail(){
       return new oldMachine();
   }
   public static Phone sendWechat(){
       return new smartPhone();
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Phone phone=Factory.sendMail();
       phone.send();
   }
}


结果:



2.抽象工厂方法模式(Abstract Factory)


工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

手机接口:


public interface Phone {
   public void send();
}


老年机:


public class oldMachine implements Phone{
   @Override
   public void send() {
       //老年机只能发短信
       System.out.println('发短信');

   }
}


智能机:


public class smartPhone implements Phone {
   @Override
   public void send() {
       //智能机可以发微信
       System.out.println('发微信');
   }
}


工厂接口:


public interface Send {
   public Phone send();
}


老年机工厂:


public class oldMachineFactory implements Send {
   @Override
   public Phone send() {
       return new oldMachine();
   }
}


智能机工厂:


public class smartPhoneFactory implements Send {
   @Override
   public Phone send() {
       return new smartPhone();
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Send send= new smartPhoneFactory();
       Phone phone=send.send();
       phone.send();
   }
}


结果:



其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Phone接口,同时做一个工厂类,实现Send接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!


3.门面模式(Facade Pattern)


比如说做饭,你得先买菜,然后洗菜,烹饪,吃;这几个过程顺序不能乱吧,而且缺一不可吧。你想想你上了一天班回来还得这么累,麻烦?麻烦!怎么解决?下馆子呗,告诉厨师你的需求,让他去干,你只需要吃就行。

做饭的过程:


//做饭的过程
public interface Cook {
   //买菜(买哪些菜)
   public void buyVegetables(String vegetables);
   //洗菜
   public void washVegetables();
   //烹饪(什么口味)
   public void cookVegetables(String flavour);
   //吃
   public void eat();
}


做饭的实现类:


//做饭的具体实现
public class cookImpl implements Cook{
   @Override
   public void buyVegetables(String vegetables) {
       System.out.println('买菜。。。。');
   }

   @Override
   public void washVegetables() {
       System.out.println('洗菜。。。。');
   }

   @Override
   public void cookVegetables(String flavour) {
       System.out.println('烹饪。。。。');
   }

   @Override
   public void eat() {
       System.out.println('吃。。。。');
   }
}


餐馆:


public class Restaurant {
   private Cook cook=new cookImpl();
   public void cook(String vegetables,String flavour){
       cook.buyVegetables(vegetables);
       cook.washVegetables();
       cook.cookVegetables(flavour);
       cook.eat();
   }
}


你去下馆子:


public class Client {
   public  static void main(String[] args){
       Restaurant rs=new Restaurant();
       //想吃鱼
       String vegetables='fish';
       //酸辣味
       String flavour='sour and hot';
       rs.cook(vegetables,flavour);
   }
}


结果:



如果厨师做饭的过程中,卫生局来检查了,刚好抽中了你这盘菜呢?

卫生局:


public class healthDepartment {
   public void check(Cook cook){};
}


修改餐厅类:


public class Restaurant {
   private Cook cook=new cookImpl();
   private healthDepartment hd=new healthDepartment();
   public void cook(String vegetables,String flavour){
       cook.buyVegetables(vegetables);
       cook.washVegetables();
       cook.cookVegetables(flavour);
       hd.check(cook);
       cook.eat();
   }
}


结果:



食材健康?健康,但是你看不到检查这个过程。

什么时候用呢?开发过程中,遇到水平比较渣的程序员,尽量安排他负责独立模块,然后封装成一个门面模式,让其他团队成员不至于看到这些烂代码糟心。


4.适配器模式(Adapter Pattern)


适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

类的适配器模式:

Source类:


public class Source {
   public void method1(){
       System.out.println('Source的method方法');
   }
}


Target接口:


public interface Target {
   //source类的方法
   public void method1();
   //新的方法
   public void method2();
}


适配器:


public class Adapter extends Source implements Target {
   @Override
   public void method2() {
       System.out.println('Target的method方法');
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Target target=new Adapter();
       target.method1();
       target.method2();
   }
}


结果:



这样Target接口的实现类就具有了Source类的功能。

 

对象的适配器模式:

基本思路和类的适配器模式相同,只是将Adapter类作修改,这次不继承Source类,而是持有Source类的实例,以达到解决兼容性的问题。

修改Adapter类:


public class Adapter implements Target {
   private Source source;

   public Adapter(Source source) {
       this.source = source;
   }

   @Override
   public void method1() {

   }

   @Override
   public void method2() {
       System.out.println('Target的method方法');
   }
}


测试:


public class Test {
   public static void main(String[] args){
       Source source=new Source();
       Target target=new Adapter(source);
       target.method1();
       target.method2();
   }
}


结果:



接口的适配器模式:

有时我们一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

接口:


public interface Target {
   //source类的方法
   public void method1();
   //新的方法
   public void method2();
}


抽象类:


public abstract class Wraaper implements Target {
   @Override
   public void method1() {

   }

   @Override
   public void method2() {

   }
}


S1:


public class S1 extends Wraaper {
   @Override
   public void method1() {
       System.out.println('S1');
   }
}


S2:


public class S2 extends Wraaper {
   @Override
   public void method2() {
       System.out.println('S2');
   }
}


测试:


public class Test {
   public static void main(String[] args){
       S1 ss=new S1();
       S2 sm=new S2();
       ss.method1();
       ss.method2();
       sm.method1();
       sm.method2();
   }
}


结果:






    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多