12.19 java设计模式

  更新:http://c.biancheng.net/design_pattern/可以看这个全面了解一下

虽然已经很久没写笔记,但是学习其实是没有停下的,我最近把几本之前买的java书籍看了一遍,以前看的时候确实是晦涩难懂的,但现在已经好多了,收获颇丰,但还是有好多地方看不太懂,慢慢来吧!

最近准备把设计模式补以下,笔记如下:

  

  java单例模式

  单例模式即是只产生一个对象的模式.在Java中,每次使用new关键字,就会产生一个新的Java对象. 有时我们需要只有一个对象产生,比如一些管理类,全局管理其它模块时,这个管理类适合采用单例模式.

普通的单例模式分为2种,懒汉式和饿汉式.懒汉式比较懒,用到的时候才创建对象,饿汉式不讲理,你用不用我都创建好放着.

普通单例模式的秘籍:

  • 将构造函数定义为私有private,只能在本类中创建,不能被继承.
  • 通过private和static关键字定义一个私有并且静态的本类实例对象,保证内存中只有1个实例,并且只有本类能调用.
  • 公开一个获得本类实例的静态方法,来获取这个实例,保证每次得到的实例都是同一个,来实现单例模式.

列出4种常用的单例模式的写法,推荐第4种. 第4种是通过内部类实现,高效且线程安全. 记住这个好了,其他的可以忘.

 

2.1 java懒汉式单例模式

java懒汉式单例模式代码:

/**
 * 懒汉式单例模式
 */
class Singleton1 {

    private static Singleton1 singleton1;

    private Singleton1() {

    }

    public static Singleton1 getInstance() {
        if (null == singleton1) {
            singleton1 = new Singleton1();
        }
        return singleton1;
    }
}
 

2.2 java饿汉式单例模式

 

/**
 * 饿汉式单例模式
 */
class Singleton2 {

    private static Singleton2 singleton2 = new Singleton2();

    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        return singleton2;
    }
}

java线程安全的懒汉式代码:

/**
 * 线程安全懒汉式单例模式
 */
class Singleton3 {

    private static Singleton3 singleton3;

    private Singleton3() {

    }

    public static synchronized Singleton3 getInstance() {
        if (null == singleton3) {
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}
 

java内部类线程安全单例模式

这种方式利用java的final关键字特性,一旦赋值无法改变.线程安全,效率高,推荐方式.java内部类线程安全单例模式示例代码:

/**
 * 内部类线程安全单例模式
 */
class Singleton4 {

    private static class SingletonHolder {
        public final static Singleton4 instance = new Singleton4();
    }

    public static Singleton4 getInstance() {
        return SingletonHolder.instance;
    }
}
 

 

2.工厂模式

 常用的工厂模式是静态工厂,利用static方法,作为一种类似于常见的工具类Utils等辅助效果,一般情况下工厂类不需要实例化。

  

 

interface food{}

class A implements food{}
class B implements food{}
class C implements food{}

public class StaticFactory {

    private StaticFactory(){}
    
    public static food getA(){  return new A(); }
    public static food getB(){  return new B(); }
    public static food getC(){  return new C(); }
}

class Client{
    //客户端代码只需要将相应的参数传入即可得到对象
    //用户不需要了解工厂类内部的逻辑。
    public void get(String name){
        food x = null ;
        if ( name.equals("A")) {
            x = StaticFactory.getA();
        }else if ( name.equals("B")){
            x = StaticFactory.getB();
        }else {
            x = StaticFactory.getC();
        }
    }
}

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

  一个基础接口定义了功能,每个实现接口的子类就是产品,然后定义一个工厂接口,实现了工厂接口的就是工厂,这时候,接口编程的优点就出现了,我们可以新增产品类(只需要实现产品接口),只需要同时新增一个工厂类,客户端就可以轻松调用新产品的代码。

  抽象工厂的灵活性就体现在这里,无需改动原有的代码,毕竟对于客户端来说,静态工厂模式在不改动StaticFactory类的代码时无法新增产品,如果采用了抽象工厂模式,就可以轻松的新增拓展类。

  实例代码:

 
interface food{}

class A implements food{}
class B implements food{}

interface produce{ food get();}

class FactoryForA implements produce{
    @Override
    public food get() {
        return new A();
    }
}
class FactoryForB implements produce{
    @Override
    public food get() {
        return new B();
    }
}
public class AbstractFactory {
    public void ClientCode(String name){
        food x= new FactoryForA().get();
        x = new FactoryForB().get();
    }
}

 

4.建造者模式(Builder)

  在了解之前,先假设有一个问题,我们需要创建一个学生对象,属性有name,number,class,sex,age,school等属性,如果每一个属性都可以为空,也就是说我们可以只用一个name,也可以用一个school,name,或者一个class,number,或者其他任意的赋值来创建一个学生对象,这时该怎么构造?

  难道我们写6个1个输入的构造函数,15个2个输入的构造函数.......吗?这个时候就需要用到Builder模式了。给个例子,大家肯定一看就懂:

 
 

public class Builder {

    static class Student{
        String name = null ;
        int number = -1 ;
        String sex = null ;
        int age = -1 ;
        String school = null ;

     //构建器,利用构建器作为参数来构建Student对象
        static class StudentBuilder{
            String name = null ;
            int number = -1 ;
            String sex = null ;
            int age = -1 ;
            String school = null ;
            public StudentBuilder setName(String name) {
                this.name = name;
                return  this ;
            }

            public StudentBuilder setNumber(int number) {
                this.number = number;
                return  this ;
            }

            public StudentBuilder setSex(String sex) {
                this.sex = sex;
                return  this ;
            }

            public StudentBuilder setAge(int age) {
                this.age = age;
                return  this ;
            }

            public StudentBuilder setSchool(String school) {
                this.school = school;
                return  this ;
            }
            public Student build() {
                return new Student(this);
            }
        }

        public Student(StudentBuilder builder){
            this.age = builder.age;
            this.name = builder.name;
            this.number = builder.number;
            this.school = builder.school ;
            this.sex = builder.sex ;
        }
    }

    public static void main( String[] args ){
        Student a = new Student.StudentBuilder().setAge(13).setName("LiHua").build();
        Student b = new Student.StudentBuilder().setSchool("sc").setSex("Male").setName("ZhangSan").build();
    }
}

5. 原型模式(Protype)

原型模式就是讲一个对象作为原型,使用clone()方法来创建新的实例。

 
public class Prototype implements Cloneable{

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected Object clone()   {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }finally {
            return null;
        }
    }

    public static void main ( String[] args){
        Prototype pro = new Prototype();
        Prototype pro1 = (Prototype)pro.clone();
    }
}

只是浅拷贝,深拷贝虚实现序列化

 

适配器模式(Adapter)

适配器模式的作用就是在原来的类上提供新功能。主要可分为3种:

  • 类适配:创建新类,继承源类,并实现新接口,例如

class adapter extends oldClass implements newFunc{}

  • 对象适配:创建新类持源类的实例,并实现新接口,例如

class adapter implements newFunc { private oldClass oldInstance ;}

  • 接口适配:创建新的抽象类实现旧接口方法。例如

abstract class adapter implements oldClassFunc { void newFunc();}


 

7.装饰模式(Decorator)

给一类对象增加新的功能,装饰方法与具体的内部逻辑无关。例如:

interface Source{ void method();}
public class Decorator implements Source{

    private Source source ;
    public void decotate1(){
        System.out.println("decorate");
    }
    @Override
    public void method() {
        decotate1();
        source.method();
    }
}

代理模式(Proxy)

客户端通过代理类访问,代理类实现具体的实现细节,客户只需要使用代理类即可实现操作。

这种模式可以对旧功能进行代理,用一个代理类调用原有的方法,且对产生的结果进行控制。

interface Source{ void method();}

class OldClass implements Source{
    @Override
    public void method() {
    }
}

class Proxy implements Source{
    private Source source = new OldClass();

    void doSomething(){}
    @Override
    public void method() {
        new Class1().Func1();
        source.method();
        new Class2().Func2();
        doSomething();
    }
}
 

.外观模式(Facade)

为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。这句话是百度百科的解释,有点难懂,但是没事,看下面的例子,我们在启动停止所有子系统的时候,为它们设计一个外观类,这样就可以实现统一的接口,这样即使有新增的子系统subSystem4,也可以在不修改客户端代码的情况下轻松完成。

 
public class Facade {
    private subSystem1 subSystem1 = new subSystem1();
    private subSystem2 subSystem2 = new subSystem2();
    private subSystem3 subSystem3 = new subSystem3();
    
    public void startSystem(){
        subSystem1.start();
        subSystem2.start();
        subSystem3.start();
    }
    
    public void stopSystem(){
        subSystem1.stop();
        subSystem2.stop();
        subSystem3.stop();
    }
}

 

10.桥接模式(Bridge)

Circle类将DrwaApi与Shape类进行了桥接,代码:

 

interface DrawAPI {
    public void drawCircle(int radius, int x, int y);
}
class RedCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle[ color: red, radius: "
                + radius +", x: " +x+", "+ y +"]");
    }
}
class GreenCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle[ color: green, radius: "
                + radius +", x: " +x+", "+ y +"]");
    }
}

abstract class Shape {
    protected DrawAPI drawAPI;
    protected Shape(DrawAPI drawAPI){
        this.drawAPI = drawAPI;
    }
    public abstract void draw();
}

class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    public void draw() {
        drawAPI.drawCircle(radius,x,y);
    }
}

//客户端使用代码
Shape redCircle = new Circle(100,100, 10, new RedCircle());
Shape greenCircle = new Circle(100,100, 10, new GreenCircle());
redCircle.draw();
greenCircle.draw();

组合模式(Composite)

组合模式是为了表示那些层次结构,同时部分和整体也可能是一样的结构,常见的如文件夹或者树。举例:

 
abstract class component{}

class File extends  component{ String filename;}

class Folder extends  component{
    component[] files ;  //既可以放文件File类,也可以放文件夹Folder类。Folder类下又有子文件或子文件夹。
    String foldername ;
    public Folder(component[] source){ files = source ;}
    
    public void scan(){
        for ( component f:files){
            if ( f instanceof File){
                System.out.println("File "+((File) f).filename);
            }else if(f instanceof Folder){
                Folder e = (Folder)f ;
                System.out.println("Folder "+e.foldername);
                e.scan();
            }
        }
    }
    
}

 

posted @ 2019-12-19 13:10  有趣的男人  阅读(163)  评论(0编辑  收藏  举报