常用设计模式

设计模式

工厂模式

  • 工厂模式思路上分:简单工厂模式,工厂模式, 抽象工厂模式
    // 抽象工厂模式可以代替工厂模式,做好抽象就好

简单工厂模式

  1. 构建顶级抽象(Product接口/抽象类)
  2. 构建二级抽象(具体product实现类)
  3. 创造工厂,通过简单判断,返回不同产品

interface Product{
    int price;
}


class CategoryAProduct implements Product {
    private final int price = 10;

    @Override
    public int price() {
        return this.price;
    }
}

class CategoryBProduct implements Product {
    private final int price = 20;

    @Override
    public int price() {
        return this.price;
    }
}

class ProductFactory {
    Product productProduct(String param) throws Exception {
        if (StringUtils.isEmpty(param)) {
            return null;
        }
        if (param.equals("A")) {
            return new A();
        } else if (param.equals("B")) {
            return new A();
        } else {
            throw new Exception();
        }
    }

    public static void main(String[] args) throws Exception {
        ProductFactory productFactory = new ProductFactory();
        Product productA = productFactory.productProduct("A");
        Product productb = productFactory.productProduct("B");
    }
}

简单的抽象化,然后利用多态获得工厂模式的生产力。

抽象工厂

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

抽象工厂模式,在简单工厂模式的基础上针对不同产品,抽象出抽象工厂这个概念,相比简单工厂模式,它在生产时不是简单的向上转型产品,而是向上转型工厂,这样一来就获得了横向拓展的能力:

interface Product {
    int price();
}

abstract class Factory {
    abstract ProductA produceProductA();
    abstract ProductB produceProductB();
}


class ProductA implements Product {
    @Override
    public int price() {
        return 10;
    }
}

class ProductB implements Product {
    @Override
    public int price() {
        return 20;
    }
}

class FactoryA extends Factory {  
// 这里的工厂A也可以做成抽象类  

    @Override
    ProductACategoryA produceProductA() {
        return new ProductACategoryA();
    }

    @Override
    ProductBCategoryA produceProductB() {
        return new ProductBCategoryA();
    }
}

class ProductACategoryA extends ProductA {
// A工厂生产的产品A
}

class ProductBCategoryA extends ProductB {
// B工厂生产的产品A
}

public static void main(String[] args) {
        FactoryA factoryA = new FactoryA();
        ProductACategoryA productACategoryA = factoryA.produceProductA();
        ProductBCategoryA productBCategoryA = factoryA.produceProductB();
    }

上面的抽象工厂模式,是1个工厂,2个产品的工厂模式,它就具有横向拓展的能力,无论是工厂增加,或者是产品增加,都可以在原有的抽象基础上直接加。(抽象组织的越好,拓展能力就会越好)

单例模式

单例模式较推荐写法:静态内部类

class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

线程安全且是懒加载

Build模式

build模式的一般使用,重在把复杂的对象构建,从传统Javabean的get set方式,变成更加连贯(可读性)和线程安全性更好的模式。

class SomethingNeedToBeBuild {
    private String filed1;
    private String filed2;

    public String getFiled1() {
        return filed1;
    }

    public void setFiled1(String filed1) {
        this.filed1 = filed1;
    }

    public String getFiled2() {
        return filed2;
    }

    public void setFiled2(String filed2) {
        this.filed2 = filed2;
    }
}  

class SomethingsBuilder {
    private final SomethingNeedToBeBuild somethingNeedToBeBuild;

    public SomethingsBuilder() {
        somethingNeedToBeBuild = new SomethingNeedToBeBuild();
    }


    public SomethingsBuilder setFiled1(String filed1) {
        this.somethingNeedToBeBuild.setFiled1(filed1);
        return this;
    }

    public SomethingsBuilder setFiled2(String filed2) {
        this.somethingNeedToBeBuild.setFiled2(filed2);
        return this;
    }

    public SomethingNeedToBeBuild build() {
        return this.somethingNeedToBeBuild;
    }
}  

public static void main(String[] args) {
        SomethingsBuilder somethingsBuilder = new SomethingsBuilder();
        SomethingNeedToBeBuild somethingNeedToBeBuild = somethingsBuilder
                .setFiled1("filed1")
                .setFiled2("field2")
                .build();

        System.out.println(somethingNeedToBeBuild.getFiled1() + somethingNeedToBeBuild.getFiled2());
    }

这是构造模式的一般业务使用逻辑:返回调用的引用来构成链式调用,并以此可变长地来传入构造参数。替代企业javabean的构建方式。
而在真正build模式,其实是外部一次性调用诸如: Something something = new SomeBuilder().build(somethings param) 就需要更加灵活地根据需求去抽象,抽象出诸如:总构造器,协助构造器(内部显式构造外部抽象调用)等,进行组合。一般开发中很少遇到。

适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式内在逻辑其实就是一层包装,然后实现外层统一调用,内部调用真正逻辑接口。
不同于代理模式,适配器的目的是为了适配,更有建议就是不是非必要的兼容,可以考虑重构,而不是加上适配器模式,过多的使用适配器,导致代码结构混乱,隐藏内在逻辑,难以理解和维护。
适配器模式按身份分为三方:

  1. 原有接口Target
  2. 现有接口但是不满足需要需要被适配 Targee
  3. 适配器类Adapter
interface Target {
    void doSomething();
}

class Targee {
    void doAnotherThing(){
        System.out.println("do another thing");
    }
}
    
class Adapter implements Target {
    private final Targee targee;

    public Adapter(Targee targee) {
        this.targee = targee;
    }

    @Override
    public void doSomething() {
        this.targee.doAnotherThing();
    }
}

public static void main(String[] args) {
        Target target = new Adapter(new Targee());
        target.doSomething();
    }

大致的思路是这样,由于设计的简单,看上去很像代理模式。但在一些框架中使用到适配器模式,会对目标Targee提供更高级别的抽象,并不只是一个实体类Targee,然后组织逻辑链,把具体适配类参数传入适配器,返回要使用的具体Target。

装饰器模式

image

装饰器模式,通过描述对象具有的行为,给对象附加上新的特性。
内部一般使用引用链来使得其具有嵌套引用的功能,从而实现通过描述到添加对象行为的过渡:

abstract class Person {
    protected abstract String getDescription();
    protected abstract void action();
}

class Young extends Person {

    @Override
    protected String getDescription() {
        return "i am a yong man";
    }

    @Override
    protected void action() {
        System.out.println("action begin: ");
    }
}

abstract class CoolDecorator extends Person {
    public abstract String getDescription();
}

abstract class WarmDecorator extends Person {
    public abstract String getDescription();
}

class Cool extends CoolDecorator {
    Person person;

    public Cool(Person person){
        this.person = person;
    }
    @Override
    public String getDescription() {
        return person.getDescription() + " cool~";
    }

    @Override
    protected void action() {
        this.person.action();
        System.out.println("cool action~");
    }
}

class Warm extends WarmDecorator {
    Person person;

    public Warm(Person person){
        this.person = person;
    }
    @Override
    public String getDescription() {
        return person.getDescription() + " warm~ ";
    }

    @Override
    protected void action() {
        person.action();
        System.out.println("warm action~");
    }
}

public static void main(String[] args) {
        Person person = new Young();

        person = new Cool(person);
        person = new Warm(person);

        System.out.println(person.getDescription());
        person.action();
    }

输出:

i am a yong man
cool~
warm~
action begin:
cool action~
warm action~

装饰者模式的精髓在于 替换思想
比如在这个例子中 Person是公共的根基,实现它的子类之间可以互相替换, 替换的实际操作靠的是引用的传递,也就是Person这个根基的引用传递。 在实际装饰操作的过程中 Person p = new Young(); p = new Cool(p); p = new Warm(p); 这里的的p看上去重复赋值,上一层赋值的会被抹除,但实际上不是这样。因为 在构造函数中传递了Person p这个公共基类,所以上一层的p在下一层中被使用, 最后使用的是最下面一层的p,但实际上已经通过传递在这个p中包含了上面n层 的p的引用,也就在最下层p的逻辑里面包含了上层所有p实例的代码逻辑。 因此这里就是起到一个装饰的作用。不停的p = new XX(p); 关键就是拓展自同一根基,然后层层引用,同时满足替换原则,最下层的是上面所有的等价实例。
这样的装饰模式的简单实用,可以把握描述对象来添加行为的方式,衍生不同的写法。

代理模式

代理模式:类似B/S架构客户端访问服务器时中间的代理服务器:

interface Server {
    void offerSomeService();
}

class ConcreteServer implements Server {
    @Override
    public void offerSomeService() {
        System.out.println("concrete server logic here");
    }
}

class Proxy implements Server {
    private final Server server;

    public Proxy(Server server) {
        this.server = server;
    }

    @Override
    public void offerSomeService() {
        doSomeProxyLogic();
        server.offerSomeService();
    }

    void doSomeProxyLogic(){
        System.out.println("proxy logic here");
    }
}

public static void main(String[] args) {
        Server server = new Proxy(new ConcreteServer());
        server.offerSomeService();
    }

输出:

proxy logic here
concrete server logic here

Server server = new Proxy(new ConcreteServer()); Server就类似实际我们需求服务的服务器,我们通过代理跟它打交道,ConcreteServer就像我们代理服务器中注册的实际服务器IP地址。

观察者模式

观察者模式思维上是,对象与对象之间存在依附关系。一个对象的动态要能让依附于其的对象感知到。

class SubjectToBeObserved {
    private List observers;

    public SubjectToBeObserved() {
        this.observers = new ArrayList<>();
    }

    public void addObserver(Observer observer) {
        this.observers.add(observer);
    }

    public void doSomethings(){
        System.out.println("subject is gonna to do something");
        nofifyAllObservers();
    }

    private void nofifyAllObservers(){
        for (Observer observer : this.observers) {
            observer.doSomethingsWhenNotified();
        }
    }

}

abstract class Observer {
    abstract void doSomethingsWhenNotified();
}

class ObserverA extends Observer {
    @Override
    void doSomethingsWhenNotified() {
        System.out.println("observer A received notification and do its own job");
    }
}

class ObserverB extends Observer {
    @Override
    void doSomethingsWhenNotified() {
        System.out.println("observer B received notification and do its own job");
    }
}


public static void main(String[] args) {
        SubjectToBeObserved subjectToBeObserved = new SubjectToBeObserved();
        ObserverA observerA = new ObserverA();
        ObserverB observerB = new ObserverB();

        subjectToBeObserved.addObserver(observerA);
        subjectToBeObserved.addObserver(observerB);

        subjectToBeObserved.doSomethings();
    }
    

输出:

subject is gonna to do something
observer A received notification and do its own job
observer B received notification and do its own job

思路就是,通过依附关系,添加了默认的执行逻辑 doSomethingsWhenNotified()
可以以此进行拓展,把具有依赖的但是显示调用耦合过高,或者代码职责分层不好做等,实现业务之间的剥离。

你可能感兴趣的:(常用设计模式)