zoukankan      html  css  js  c++  java
  • 设计模式系列

    结构设计模式向您展示了如何以灵活和可扩展的方式将系统的不同部分粘合在一起。它们可以帮助您保证当其中一个部分发生更改时,整个结构不需要更改。
    这些模式关注的是类之间如何相互继承,以及它们是如何由其他类组成的。结构模式使用继承来组合接口或实现。

    适配器模式

    适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
    这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
    关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。

    //步骤 1
    //为媒体播放器和更高级的媒体播放器创建接口。
    
    //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);
    }
    //步骤 2
    //创建实现了 AdvancedMediaPlayer 接口的实体类。
    
    //VlcPlayer.java
    public class VlcPlayer implements AdvancedMediaPlayer{
       @Override
       public void playVlc(String fileName) {
          System.out.println("Playing vlc file. Name: "+ 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.out.println("Playing mp4 file. Name: "+ fileName);      
       }
    }
    //步骤 3
    //创建实现了 MediaPlayer 接口的适配器类。
    
    //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);
          }
       }
    }
    //步骤 4
    //创建实现了 MediaPlayer 接口的实体类。
    
    //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");
          }
       }   
    }
    //步骤 5
    //使用 AudioPlayer 来播放不同类型的音频格式。
    
    //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");
       }
    }
    步骤 6
    执行程序,输出结果:
    
    Playing mp3 file. Name: beyond the horizon.mp3
    Playing mp4 file. Name: alone.mp4
    Playing vlc file. Name: far far away.vlc
    Invalid media. avi format not supported

    桥接模式

    桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
    桥设计模式用于将一个类分解为两个部分——抽象和它的实现——以便这两个部分在将来都能在不影响彼此的情况下发展。它增加了类抽象和它的实现之间的松散耦合。
    这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

    当您必须以相互正交的方式对不同时间进行子类化时,它变得很方便。
    例如,假设您正在创建具有不同颜色的各种图形用户界面形状。一种解决方案可能是:

    但上述解决方案存在问题。如果您想更改Rectange类,那么您也可能最终更改BlueRectangle和RedRectangle,即使更改是颜色特定的,那么您也可能需要更改Circle类。
    您可以通过以下方式分离形状和颜色接口来解决上述问题。

    //首先是形状类:该类为一个抽象类,主要提供画形状的方法 Shape.java :
    public abstract class Shape {
        Color color;
     
        public void setColor(Color color) {
            this.color = color;
        }
        
        public abstract void draw();
    }
    //然后是三个形状 。
    //圆形 Circle.java :
    public class Circle extends Shape{
     
        public void draw() {
            color.bepaint("正方形");
        }
    }
    //长方形 Rectangle.java :
    public class Rectangle extends Shape{
     
        public void draw() {
            color.bepaint("长方形");
        }
     
    }
    //正方形 Square.java :
    public class Square extends Shape{
     
        public void draw() {
            color.bepaint("正方形");
        }
     
    }
    //颜色接口 Color.java :
    public interface Color {
        public void bepaint(String shape);
    }
    //白色 White.java :
    public class White implements Color{
     
        public void bepaint(String shape) {
            System.out.println("白色的" + shape);
        }
     
    }
    //灰色 Gray.java :
    public class Gray implements Color{
     
        public void bepaint(String shape) {
            System.out.println("灰色的" + shape);
        }
    }
    //黑色 Black.java :
    public class Black implements Color{
     
        public void bepaint(String shape) {
            System.out.println("黑色的" + shape);
        }
    }
    //客户端 Client.java :
    public class Client {
        public static void main(String[] args) {
            //白色
            Color white = new White();
            //正方形
            Shape square = new Square();
            //白色的正方形
            square.setColor(white);
            square.draw();
            
            //长方形
            Shape rectange = new Rectangle();
            rectange.setColor(white);
            rectange.draw();
        }
    }
    运行结果:
    
    白色的正方形
    白色的长方形

    组合模式

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
    组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
    这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。复合设计模式是一种修改对象结构的结构模式。这种模式最适合于需要处理形成树状层次结构的对象的情况。在该树中,每个节点/对象(根节点除外)都是复合节点或叶节点。实现复合模式允许客户机统一地处理单个对象和组合。

    import java.util.ArrayList; 
    import java.util.List; 
      
      
    // A common interface for all employee 
    interface Employee 
    { 
        public void showEmployeeDetails(); 
    } 
      
    class Developer implements Employee 
    { 
        private String name; 
        private long empId; 
        private String position; 
          
        public Developer(long empId, String name, String position) 
        { 
            // Assign the Employee id, 
            // name and the position 
            this.empId = empId; 
            this.name = name; 
            this.position = position; 
        } 
          
        @Override
        public void showEmployeeDetails()  
        { 
            System.out.println(empId+" " +name+ " " + position ); 
        } 
    } 
      
    class Manager implements Employee 
    { 
        private String name; 
        private long empId; 
        private String position; 
       
        public Manager(long empId, String name, String position) 
        { 
            this.empId = empId; 
            this.name = name; 
            this.position = position; 
        } 
           
        @Override
        public void showEmployeeDetails()  
        { 
            System.out.println(empId+" " +name+ " " + position ); 
        } 
    } 
      
      
    // Class used to get Employee List 
    // and do the opertions like  
    // add or remove Employee 
      
    class CompanyDirectory implements Employee 
    { 
        private List<Employee> employeeList = new ArrayList<Employee>(); 
            
        @Override
        public void showEmployeeDetails()  
        { 
            for(Employee emp:employeeList) 
            { 
                emp.showEmployeeDetails(); 
            } 
        } 
            
        public void addEmployee(Employee emp) 
        { 
            employeeList.add(emp); 
        } 
            
        public void removeEmployee(Employee emp) 
        { 
            employeeList.remove(emp); 
        } 
    } 
      
    // Driver class 
    public class Company 
    { 
        public static void main (String[] args) 
        { 
            Developer dev1 = new Developer(100, "Lokesh Sharma", "Pro Developer"); 
            Developer dev2 = new Developer(101, "Vinay Sharma", "Developer"); 
            CompanyDirectory engDirectory = new CompanyDirectory(); 
            engDirectory.addEmployee(dev1); 
            engDirectory.addEmployee(dev2); 
               
            Manager man1 = new Manager(200, "Kushagra Garg", "SEO Manager"); 
            Manager man2 = new Manager(201, "Vikram Sharma ", "Kushagra's Manager"); 
               
            CompanyDirectory accDirectory = new CompanyDirectory(); 
            accDirectory.addEmployee(man1); 
            accDirectory.addEmployee(man2); 
           
            CompanyDirectory directory = new CompanyDirectory(); 
            directory.addEmployee(engDirectory); 
            directory.addEmployee(accDirectory); 
            directory.showEmployeeDetails(); 
        } 
    } 
    Output :
    
    100 Lokesh Sharma Pro Developer
    101 Vinay Sharma Developer
    200 Kushagra Garg SEO Manager
    201 Vikram Sharma  Kushagra's Manager

    装饰器模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
    这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
    关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。

    // Abstract Pizza class (All classes extend 
    // from this) 
    abstract class Pizza 
    { 
        // it is an abstract pizza 
        String description = "Unkknown Pizza"; 
      
        public String getDescription() 
        { 
            return description; 
        } 
      
        public abstract int getCost(); 
    } 
      
    // The decorator class :  It extends Pizza to be 
    // interchangable with it topings decorator can 
    // also be implemented as an interface 
    abstract class ToppingsDecorator extends Pizza 
    { 
        public abstract String getDescription(); 
    } 
      
    // Concrete pizza classes 
    class PeppyPaneer extends Pizza 
    { 
        public PeppyPaneer() { description = "PeppyPaneer"; } 
        public int getCost() {  return 100; } 
    } 
    class FarmHouse extends Pizza 
    { 
        public FarmHouse() {  description = "FarmHouse"; } 
        public int getCost() { return 200; } 
    } 
    class Margherita extends Pizza 
    { 
        public Margherita()  { description = "Margherita"; } 
        public int getCost() { return 100;  } 
    } 
    class ChickenFiesta extends Pizza 
    { 
        public ChickenFiesta() { description = "ChickenFiesta";} 
        public int getCost() { return 200; } 
    } 
    class SimplePizza extends Pizza 
    { 
    public SimplePizza() { description = "SimplePizza"; } 
    public int getCost() {  return 50;  } 
    } 
      
    // Concrete toppings classes 
    class FreshTomato extends ToppingsDecorator 
    { 
        // we need a reference to obj we are decorating 
        Pizza pizza; 
      
        public FreshTomato(Pizza pizza) { this.pizza = pizza; } 
        public String getDescription() { 
            return pizza.getDescription() + ", Fresh Tomato "; 
        } 
        public int getCost() { return 40 + pizza.getCost(); } 
    } 
    class Barbeque extends ToppingsDecorator 
    { 
        Pizza pizza; 
        public Barbeque(Pizza pizza) {  this.pizza = pizza;  } 
        public String getDescription() { 
            return pizza.getDescription() + ", Barbeque "; 
        } 
        public int getCost() { return 90 + pizza.getCost(); } 
    } 
    class Paneer extends ToppingsDecorator 
    { 
        Pizza pizza; 
        public Paneer(Pizza pizza)  {  this.pizza = pizza; } 
        public String getDescription() { 
            return pizza.getDescription() + ", Paneer "; 
        } 
        public int getCost()  {  return 70 + pizza.getCost(); } 
    } 
      
    // Other toppings can be coded in a similar way 
    // Driver class and method 
    class PizzaStore 
    { 
        public static void main(String args[]) 
        { 
            // create new margherita pizza 
            Pizza pizza = new Margherita(); 
            System.out.println( pizza.getDescription() + 
                             " Cost :" + pizza.getCost()); 
      
            // create new FarmHouse pizza 
            Pizza pizza2 = new FarmHouse(); 
      
            // decorate it with freshtomato topping 
            pizza2 = new FreshTomato(pizza2); 
      
            //decorate it with paneer topping 
            pizza2 = new Paneer(pizza2); 
      
            System.out.println( pizza2.getDescription() + 
                             " Cost :" + pizza2.getCost()); 
            Pizza pizza3 = new Barbeque(null);    //no specific pizza 
            System.out.println( pizza3.getDescription() + "  Cost :" + pizza3.getCost()); 
       } 
    } 
    Output:
    
    Margherita Cost :100
    FarmHouse, Fresh Tomato , Paneer Cost :310

    外观模式

    外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
    这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
    关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。

    //步骤 1
    //创建一个接口。
    //Shape.java
    public interface Shape {
       void draw();
    }
    //步骤 2
    //创建实现接口的实体类。
    Rectangle.java
    public class Rectangle implements Shape {
     
       @Override
       public void draw() {
          System.out.println("Rectangle::draw()");
       }
    }
    Square.java
    public class Square implements Shape {
     
       @Override
       public void draw() {
          System.out.println("Square::draw()");
       }
    }
    Circle.java
    public class Circle implements Shape {
     
       @Override
       public void draw() {
          System.out.println("Circle::draw()");
       }
    }
    //步骤 3
    //创建一个外观类。
    ShapeMaker.java
    public class ShapeMaker {
       private Shape circle;
       private Shape rectangle;
       private Shape square;
     
       public ShapeMaker() {
          circle = new Circle();
          rectangle = new Rectangle();
          square = new Square();
       }
     
       public void drawCircle(){
          circle.draw();
       }
       public void drawRectangle(){
          rectangle.draw();
       }
       public void drawSquare(){
          square.draw();
       }
    }
    //步骤 4
    //使用该外观类画出各种类型的形状。
    FacadePatternDemo.java
    public class FacadePatternDemo {
       public static void main(String[] args) {
          ShapeMaker shapeMaker = new ShapeMaker();
     
          shapeMaker.drawCircle();
          shapeMaker.drawRectangle();
          shapeMaker.drawSquare();      
       }
    }
    //步骤 5
    //执行程序,输出结果:
    
    Circle::draw()
    Rectangle::draw()
    Square::draw()


    享元模式

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
    享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

    Pen.java
    public interface Pen 
    {   
        public void setColor(String color);
        public void draw(String content); 
    }
    BrushSize.java
    public enum BrushSize {
        THIN, MEDIUM, THICK
    }
    ThickPen.java
    public class ThickPen implements Pen {
         
        final BrushSize brushSize = BrushSize.THICK;    //intrinsic state - shareable
        private String color = null;                    //extrinsic state - supplied by client
         
        public void setColor(String color) {
            this.color = color;
        }
     
        @Override
        public void draw(String content) {
            System.out.println("Drawing THICK content in color : " + color);
        }
    }
    ThinPen.java
    public class ThinPen implements Pen {
         
        final BrushSize brushSize = BrushSize.THIN;
        private String color = null; 
         
        public void setColor(String color) {
            this.color = color;
        }
     
        @Override
        public void draw(String content) {
            System.out.println("Drawing THIN content in color : " + color);
        }
    }
    MediumPen.java
    public class MediumPen implements Pen {
         
        final BrushSize brushSize = BrushSize.MEDIUM;
        private String color = null; 
         
        public void setColor(String color) {
            this.color = color;
        }
     
        @Override
        public void draw(String content) {
            System.out.println("Drawing MEDIUM content in color : " + color);
        }
    }
    
    
    PenFactory.java
    import java.util.HashMap;
     
    public class PenFactory 
    {
        private static final HashMap<String, Pen> pensMap = new HashMap<>();
     
        public static Pen getThickPen(String color) 
        {
            String key = color + "-THICK";
             
            Pen pen = pensMap.get(key);
             
            if(pen != null) {
                return pen;
            } else {
                pen = new ThickPen();
                pen.setColor(color);
                pensMap.put(key, pen);
            }
             
            return pen;
        }
         
        public static Pen getThinPen(String color) 
        {
            String key = color + "-THIN";
             
            Pen pen = pensMap.get(key);
             
            if(pen != null) {
                return pen;
            } else {
                pen = new ThinPen();
                pen.setColor(color);
                pensMap.put(key, pen);
            }
             
            return pen;
        }
         
        public static Pen getMediumPen(String color) 
        {
            String key = color + "-MEDIUM";
             
            Pen pen = pensMap.get(key);
             
            if(pen != null) {
                return pen;
            } else {
                pen = new MediumPen();
                pen.setColor(color);
                pensMap.put(key, pen);
            }
             
            return pen;
        }
    }
    
    PaintBrushClient.java
    public class PaintBrushClient 
    {
        public static void main(String[] args) 
        {
            Pen yellowThinPen1 = PenFactory.getThickPen("YELLOW");  //created new pen
            yellowThinPen1.draw("Hello World !!");
             
            Pen yellowThinPen2 = PenFactory.getThickPen("YELLOW");  //pen is shared
            yellowThinPen2.draw("Hello World !!");
             
            Pen blueThinPen = PenFactory.getThickPen("BLUE");       //created new pen
            blueThinPen.draw("Hello World !!");
             
            System.out.println(yellowThinPen1.hashCode());
            System.out.println(yellowThinPen2.hashCode());
             
            System.out.println(blueThinPen.hashCode());
        }
    }
    Program output.
    
    Console
    Drawing THICK content in color : YELLOW
    Drawing THICK content in color : YELLOW
    Drawing THICK content in color : BLUE
     
    2018699554      //same object
    2018699554      //same object
    1311053135

    代理模式

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
    代理对象为另一个对象提供代理项或占位符以控制对它的访问。代理基本上是对我们创建的预期对象的替代,因为许多原因,例如安全原因或创建完全初始化的原始对象的相关成本。
    何时使用代理设计模式?
    代理对象隐藏原始对象并控制对其的访问。当我们想使用一个可以作为其他对象接口的类时,我们可以使用代理。
    代理被大量用于实现延迟加载相关的用例,在这些用例中,我们不希望在实际需要之前创建完整的对象。
    代理也可以用于在原始对象周围添加附加的安全层。

    RealObject.java
    public interface RealObject 
    {
        public void doSomething();
    }
    RealObjectImpl.java
    public class RealObjectImpl implements RealObject {
     
        @Override
        public void doSomething() {
            System.out.println("Performing work in real object");
        }
     
    }
    RealObjectProxy.java
    public class RealObjectProxy extends RealObjectImpl 
    {
        @Override
        public void doSomething() 
        {
            //Perform additional logic and security
            //Even we can block the operation execution
            System.out.println("Delegating work on real object");
            super.doSomething();
        }
    }
    Client.java
    public class Client 
    {
        public static void main(String[] args) 
        {
            RealObject proxy = new RealObjectProxy();
            proxy.doSomething();
        }
    }
    Program output.
    
    Console
    Delegating work on real object
    Performing work in real object
  • 相关阅读:
    springMVC准确定位多个参数对象的属性
    java正则表达式应用
    mybatis与mysql插入数据返回主键
    xml文件中怎么写小于号 等特殊符号
    sqlserver 分页查询 举例
    Python报错:IndentationError: expected an indented block
    统计输入的汉字,数字,英文,other数量
    easyui+ajax获取同表关联的数据
    JAVA死锁
    mybatis自动生成mapper,dao映射文件
  • 原文地址:https://www.cnblogs.com/starcrm/p/12606512.html
Copyright © 2011-2022 走看看