设计模式学习

201 阅读8分钟

Java面向对象编程思想

封装 继承 多态

Java设计模式的七个原则

1.开放--封闭原则

对于扩展是保持开放的原则,对于修改属于封闭的原则.
public class Father {
    void job();
}
扩展 -- 一般的情况都是继承父类或者实现接口,通过对自身的修改达到一定的效果.
public class Son1 extends Father {
    public void sonJob() {
        super.job();
        .....
    }
}
修改 -- 指的是为了完成某种效果对自身已有的稳定的代码结构进行修改.这种操作一般是不安全的,很容导致修改之后的代
码出现不稳定的情况.

2.依赖倒置原则

抽象不应该依赖细节,细节应该依赖于抽象.
举个例子:(盗用大话设计模式中的电脑组成的列子)电脑的组成由主板、CPU、内存、显卡等这些东西组合在一起就是一台电脑主机,但是这些东西中的一个发生了损坏的情况下,是不是就表示整个主机不能使用了呢,并不是这个样子的因为这些个组建其实就是利用了上面所说的实现依赖抽象,而不是抽象依赖于实现的,就拿内存来说吧,它是安装在主板上的,它跟主板之间的关联是通过接口进行的关联的,而不是主板根据它是什么样的去定制只适合它的接口,所以如果内存出现问题我们只要更换出现问题的内存即可,而不是说整个主机都不能跟着使用了。在程序开发中也是同样的,开发的某种功能主要是依赖于抽象。这样方便程序的扩展以及复用。

3.里氏替换原则

子类型必须能够替换它们的父类型。多态的体现

class Animal {
    void 叫();
    void 跑();
    void 跳()
}
class Cat extends Animal {
    void 叫(){
        System.err.printfln("猫叫");
    }
    ...
}
class Dog extends Animal {
    void 叫(){
        System.err.printfln("狗叫");
    }
    ...
}
public static void main(String[] args) {
    //这是直接使用父类对象
    Animal animal = new Animal();
    animal.叫();
    //将父类引用指向子类对象
    animal = new Cat();
    animal.叫();
    animal = new Dog();
    animal.叫();
}

上面的例子就可以看出里氏替换原则就是要让子类可以随时随地的替换父类出现同时不改变程序原有的功能。

4.单一职责原则

对于一个类来说只有一种原因能够引起其变化.例如: MVP设计模式中的V(View-->Activity)层,只是用来与用户进行界面交互的,那么这个V层的所有类只能是当页面发生了某种变化的时候对应的类才会发生变化.而其他的例如逻辑处理网络请求什么则不应该放在当前V层的类中.

5.迪米特法则

迪米特法则又叫最少知识原则,表示不同的类最大程度的解耦。这个原则表达的意思就是两个类如果没有直接的交互,那么这两个类不要有直接的引用。这样会造成耦合度增大不利于解耦。

6.接口隔离原则

不要使用一个单一的总接口,接口也需要根据引起它的变化规则进行拆分。比如数据库操作的接口就不要和网络请求数据的接口组合到一个接口中,这样首先不符合单一职责原则,同时使的这个接口的冗余度过大不利于代码的维护。

7.合成复用原则

使用类的时候尽量是组合的模式,不要使用继承的方式。

设计模式

1.单例模式

对外提供的对象始终只有一个分为懒汉式和饿汉式。
懒汉式:

public class SingleIdler {
    public static volatile SingleIdlerSingleIdlerSingleIdler mInstance;
    
    public static SingleIdlerSingleIdler getInstance() {
        if(mInstance == null) {
            synchronized(SingleIdler.class) {
                if(mInstance ==  null){
                    mInstance = new SingleTon();
                }
            }
        }
        return mInstance;
    }
}

饿汗式

public class SingleHungarySweat {
    public static final SingleHungarySweat mInstance = new SingleHungarySweat();
    public static void SingleHungarySweat getInstance() {
        return mIntstance;
    }
}

2.工厂设计模式

1.简单工厂

简单工厂就是工厂根据不同的标志创建出不同的对象.
简单工厂

interface Animal {
    void 叫();
}
public class Cat implement Animal {
    void 叫() {
        System.err.printfln("猫叫");
    }
}
public class Dog implement Animal {
    void 叫() {
        System.err.printfln("狗叫");
    }
}

public class SimpleFactory {
    public static Animal getAnimal(Class clazz) {
        Animal animal = null;
        if(clazz instanceof Cat.class) {
            animal = new Cat();
        } else if(clazz instanceof Dog.class){
            animal = new Dog();
        } else {
            animal = new Animal {
                void 叫() {
                    
                }
            };
        }
        return animal;
    }
}

2.工厂方法

工厂方法就是有一个抽象的工厂只提供单纯的产品创建思路不负责具体的产品创建流程. 工厂方法中四个主要组成部分:
抽象工厂
具体工厂
抽象产品
具体产品

public interface Product {
    void product();
}
public interface Factory {
    void Product createProduct();
}
public class FactoryA implements Factory 
    @Override
    public void Product createProduct() {
        return new ProductA();
    }
}

public class ProductA implements Product {
    @Override
    public void product() {
        System.err.printfln("A类产品已经生产完成");
    }
}
public class Client {
    public static void main(String[] args) {
        Factory factory = new FactoryA();
        Product product = factory.createProduct();
        product.product();
    }
}

3.抽象工厂

抽象工厂是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 UML类图的代码如下:

public interface Shape {
    void draw();
}

public class Rectangle implements Shape {
    @Override
    pulic void draw() {
        System.err.printfln("Rectangle+draw");
    }
}

public class Square implements Shape {
    @Override
    pulic void draw() {
        System.err.printfln("Square+draw");
    }
}

public class Circle implements Shape {
    @Override
    pulic void draw() {
        System.err.printfln("Circle+draw");
    }
}

public interface Color {
    void fill();
}

public class  Red implements Color {
    @Override
    public void fill() {
        System.err.printfln("Red + color");
    }
}

public class  Green implements Color {
    @Override
    public void fill() {
        System.err.printfln("Green + color");
    }
}

public class  Blue implements Color {
    @Override
    public void fill() {
        System.err.printfln("Blue + color");
    }
}

public interface AbstractFactory {
    Shape getShape(String shapeString);
    Color getColor(String colorString);
}
//形状的工厂
public class ShapeFactory implements AbstractFactory {
    @Override
    public Shape getShape(String shapeString) {
        if(shapeString.equals("Rectangle")) {
            return new Rectangle();
        } else if(shapeString.equals("Square")) {
            return new Square();
        }else {
            return new Circle();
        }
    }
    @Override 
    public Color getColor (String colorString) {}
}
//颜色的工厂
public class ColorFactory implements AbstractFactory {
    @Override
    public Shape getShape(String shapeString) {}
    @Override
    public Color getColor(String colorString) {
        if(colorString.equals("red")) {
            return new Red();
        } else if (colorString.equals("blue")) {
            return new Blue();
        } else {
            return new Green();
        }
    }
}

//创建工厂的工厂
public class FactoryProducer {
    public AbstractFactory getFactory(String factoryString) {
        if(factoryString.equals("shape")){
            return new ShapeFactory();
        }else {
            return new ColorFactory();
        }
    }
}
//最终调用的客户端
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
      //获取形状工厂
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
      //获取形状为 Circle 的对象
      Shape shape1 = shapeFactory.getShape("CIRCLE");
      //调用 Circle 的 draw 方法
      shape1.draw();
      //获取形状为 Rectangle 的对象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
      //调用 Rectangle 的 draw 方法
      shape2.draw();
      //获取形状为 Square 的对象
      Shape shape3 = shapeFactory.getShape("SQUARE");
      //调用 Square 的 draw 方法
      shape3.draw();
      //获取颜色工厂
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
      //获取颜色为 Red 的对象
      Color color1 = colorFactory.getColor("RED");
      //调用 Red 的 fill 方法
      color1.fill();
      //获取颜色为 Green 的对象
      Color color2 = colorFactory.getColor("Green");
      //调用 Green 的 fill 方法
      color2.fill();
      //获取颜色为 Blue 的对象
      Color color3 = colorFactory.getColor("BLUE");
      //调用 Blue 的 fill 方法
      color3.fill();
    }
}

3.建造者模式

建造者模式使用多个简单的对象一步一步的建成一个复杂的对象,这种类型的设计模式属于创建型模式。意图是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。下图是以一个麦当劳创建汉堡饮品套餐为列子展示的UML类图。 www.runoob.com/wp-content/… UML类图的代码如下:

Item.java

public interface Item {
    public String name();
    public Packing packing();
    public float price();
}

Packing.java

public interface Packing {
    public String pack();
}

Wrapper.java

public class Wrapper implements Packing {
    public String pack() {
        return "Wrapper";
    }
}

Bottle.java

public class Bottle implements Packing {
    return "Bottle";
}

Burger.java

public abstract class Burger implements Item {
    public String name();
    public Packing packing() {
        return new Wrapper();
    }
    public float price();
}

ColdDrink.java

public abstract class ColdDrink implements Item {
    public String name();
    public Packing packing() {
        return new Bottle();
    }
    public float price();
}

VegBurger.java

public class VegBurger extends Burger {
    public String name() {
        return "VegBurger";
    }
    public float price() {
        return 25.0f;
    }
}

ChickBurger.java

public class ChickenBurger extends Burger {
    public String name() {
        return "ChickenBurger";
    }
    public float price() {
        return 50.0f
    }
}

Meal.java

import java.util.ArrayList;
import java.util.List;
 
public class Meal {
   private List<Item> items = new ArrayList<Item>();    
 
   public void addItem(Item item){
      items.add(item);
   }
 
   public float getCost(){
      float cost = 0.0f;
      for (Item item : items) {
         cost += item.price();
      }        
      return cost;
   }
 
   public void showItems(){
      for (Item item : items) {
         System.out.print("Item : "+item.name());
         System.out.print(", Packing : "+item.packing().pack());
         System.out.println(", Price : "+item.price());
      }        
   }    
}

MealBuilder.java

public class MealBuilder {
 
   public Meal prepareVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new VegBurger());
      meal.addItem(new Coke());
      return meal;
   }   
 
   public Meal prepareNonVegMeal (){
      Meal meal = new Meal();
      meal.addItem(new ChickenBurger());
      meal.addItem(new Pepsi());
      return meal;
   }
}

BuilderPatternDemo.java

public class BuilderPatternDemo {
   public static void main(String[] args) {
      MealBuilder mealBuilder = new MealBuilder();
 
      Meal vegMeal = mealBuilder.prepareVegMeal();
      System.out.println("Veg Meal");
      vegMeal.showItems();
      System.out.println("Total Cost: " +vegMeal.getCost());
 
      Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
      System.out.println("\n\nNon-Veg Meal");
      nonVegMeal.showItems();
      System.out.println("Total Cost: " +nonVegMeal.getCost());
   }
}

4.适配器模式

适配器模式是作为将两个不兼容的接口之间的桥梁,这种类型的设计模式属于结构型模式。意图讲一个类的接口转换成客户希望的另一个接口。适配器模式是的原本由于接口不兼容而不能一起工作的那些类可以一起工作。 www.runoob.com/wp-content/…

MediaPlayer.java

public interface MediaPlayer {
    public void play(String audioType,String fileName);
}

AdvancedMediaPlayer.java

public interface AdvancedMediaPlayer {
    public void playVlc(String fileName);
    public void playMp4(String fileName);
}

VlcPlayer.java

public class VlcPlayer implements AdvancedMediaPlayer {
    @Override 
    public void playVlc(String fileName) {
        System.err.printfln("play vlc filename");
    }
    
    @Override
    public void playMp4(String fileName){}
}

Mp4Player.java

public class Mp4Player implements AdvancedMediaPlayer {
    @Override 
    public void playVlc(String fileName) {
       
    }
    
    @Override
    public void playMp4(String fileName){
         System.err.printfln("play mp4 filename");
    }
}

MediaAdapter.java

public class MediaAdapter implements MediaPlayer {
 
   AdvancedMediaPlayer advancedMusicPlayer;
 
   public MediaAdapter(String audioType){
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();       
      } else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }
 
   @Override
   public void play(String audioType, String fileName) {
      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

AudioPlayer.java

public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter; 
 
   @Override
   public void play(String audioType, String fileName) {    
 
      //播放 mp3 音乐文件的内置支持
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: "+ fileName);         
      } 
      //mediaAdapter 提供了播放其他文件格式的支持
      else if(audioType.equalsIgnoreCase("vlc") 
         || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      else{
         System.out.println("Invalid media. "+
            audioType + " format not supported");
      }
   }   
}

AdapterPatternDemo.java

public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();
 
      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}