设计模式学习

现在是在电信部门实习,每天空闲时间较多,所以就复习了一下设计模式。

1. 工厂方法模式

工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

2. 抽象工厂模式

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

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

3. 单例模式

网上有关单例模式的例子很多,这里采用多线程的单例模式。

优点:

  ①某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

  ②省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

  ③有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

/**
 * 多线程的单例模式,使用双重校验机制
* 使用多线程的单例模式的原因是:在多线程环境下,创建类的实例会出现问题,必须要对创建类的函数加上synchronized关键字,以防止实例化两个或者以上的实例。
*/ public class DoubleCheckMode { private volatile static DoubleCheckMode sDoubleCheckMode ; public DoubleCheckMode() { System.out.println(" created " + getClass().getSimpleName()); } public static DoubleCheckMode getInstance() { if (sDoubleCheckMode == null) synchronized (DoubleCheckMode.class) { if (sDoubleCheckMode == null) { sDoubleCheckMode = new DoubleCheckMode(); } } return sDoubleCheckMode; } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread() { @Override public void run() { super.run(); System.out.println("thread" + getId()); DoubleCheckMode.getInstance(); } }.start(); } } }

或者

            使用静态内部实现的单例是懒加载的且线程安全。
            从网上资料得出如下结论:加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生。
public class Singleton {

    /* 私有构造方法,防止被实例化 */
    private Singleton() {
    }

    /* 此处使用一个内部类来维护单例 */
    private static class SingletonFactory {
        private static final Singleton instance = new Singleton();
    }

    /* 获取实例 */
    public static Singleton getInstance() {
        return SingletonFactory.instance;
    }

    /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */
    public Object readResolve() {
        return getInstance();
    }
}

或者

public class SingletonTest {

    private static SingletonTest instance = null;

    private SingletonTest() {
    }

    private static synchronized void syncInit() {
        if (instance == null) {
            instance = new SingletonTest();
        }
    }

    public static SingletonTest getInstance() {
        if (instance == null) {
            syncInit();
        }
        return instance;
    }
}

4. 建造者模式

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到的。

public class Builder {
    
    private List<Sender> list = new ArrayList<Sender>();
    
    public void produceMailSender(int count){
        for(int i=0; i<count; i++){
            list.add(new MailSender());
        }
    }
    
    public void produceSmsSender(int count){
        for(int i=0; i<count; i++){
            list.add(new SmsSender());
        }
    }
    public static void main(String[] args) {
        Builder builder = new Builder();
        builder.produceMailSender(10);
    }
}

从这点看出,建造者模式将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。所以与工程模式的区别就是:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象,多个部分。因此,是选择工厂模式还是建造者模式,依实际情况而定。

5. 原型模式

原型模式就是讲一个对象作为原型,使用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();
    }
}

 6.  适配器模式

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

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

class  adapter extends oldClass  implements newFunc{}

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

class adapter implements newFunc { private oldClass oldInstance ;}

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

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

7. 装饰模式

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

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(); } }

8. 代理模式

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

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

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();
    }
}

9. 外观模式

为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。这句话是百度百科的解释,有点难懂,但是没事,看下面的例子,我们在启动停止所有子系统的时候,为它们设计一个外观类,这样就可以实现统一的接口,这样即使有新增的子系统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. 桥接模式

11. 组合模式

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

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();
            }
        }
    }
    
}

12. 享元模式

 使用共享对象的方法,用来尽可能减少内存使用量以及分享资讯。通常使用工厂类辅助,例子中使用一个HashMap类进行辅助判断,数据池中是否已经有了目标实例,如果有,则直接返回,不需要多次创建重复实例。

abstract class flywei{ }

public class Flyweight extends flywei{
    Object obj ;
    public Flyweight(Object obj){
        this.obj = obj;
    }
}

class  FlyweightFactory{
    private HashMap<Object,Flyweight> data;

    public FlyweightFactory(){ data = new HashMap<>();}

    public Flyweight getFlyweight(Object object){
        if ( data.containsKey(object)){
            return data.get(object);
        }else {
            Flyweight flyweight = new Flyweight(object);
            data.put(object,flyweight);
            return flyweight;
        }
    }
}

posted @ 2019-01-08 10:24  孔乙己的茴香豆  阅读(118)  评论(0)    收藏  举报