首先单例模式:
单例模式:如果需求中要求对一个类只能实例化一次,也就是只能有一个对象内存地址,那么就可以使用单例模式了
package com.schema;
/**
* 懒汉式,就是说当用的时候在进行实例化对象,这样的话相对于饿汉式来说就不会浪费资源,因为只有当用的时候才会进行实例化
* 但是会可能会造成线程安全问题
*/
public class Person {
private static Person person;
private Person() {
}
static {
System.out.println("nihao");
}
public static Person getPerson() {
if (null == person) {
person = new Person();
return person;
} else {
return person;
}
}
// synchronized 多线程使用此关键字便可防止线程安全问题,但同时也可能会造成效率降低的问题
/*public synchronized static Person getPerson() {
if (null == person) {
person = new Person();
return person;
} else {
return person;
}
}*
}
/**
* 饿汉式,先吃再说
* 类加载了,就会创建对象,但这样相对于我们如果没有用到这个单例对象的话就将造成资源的浪费
*/
class Person2 {
private static Person2 person2 = new Person2();
private Person2(){
}
public static Person2 getPerson2(){
return person2;
}
}
class Test{
public static void main(String[] args) {
Person2 person = Person2.getPerson2();
System.out.println(person);
Person2 person2 = Person2.getPerson2();
System.out.println(person2);
}
}
工厂模式:-简单工厂模式
工厂模式理解:
package com.schema;
/**
* 工厂模式
* 工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。
* 如果创建对象B的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。我们可以这些创建对象B的代码放到工厂里统一管理。
* 由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。比如想把所有调用B的地方改成B的子类B1,
* 只需要在对应生产B的工厂中或者工厂的方法中修改其生产的对象为B1即可,而不需要找到所有的new B()改为new B1()。
* 比如我有一个例子:接口为animal接口,但是它下面有多个子类实现了这个接口,比如 dog、cat、pig、tiger、bird等等,那我们是不是每个animal业务需要这个接口的对象去实例化它的子类,
* 那么它的每个实现类中又有多个属性需要初始化,然后我们才能使用对象去调用方法,那么这边问题来了,如果我们这个业务流程需要改变接口实例化的实现类,比如改成子类,是不是所有实例化过这个类的代码都得改。
* 工厂模式适用的一些场景(不仅限于以下场景):
* 1. 对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。
* 2. 类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
* 优点:
* 1、调用者只需要知道名称即可,不需要了解具体实现。屏蔽具体实现细节。(信息安全)
* 2、扩展性高。如果想增加一个产品,只要扩展一个工厂类即可。
* 缺点:
* 1、每增加一个产品,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,一定程序上增加了系统的复杂度。
* 2、增加了系统具体类的依赖。
* 3、不符合开闭-原则。即对扩展开发、对修改关闭。因为每增加一个动物类,需要在工厂代码里面增加if-else判断。
* 4、简单工厂模式其实不是一个设计模式,反而比较像是一种编程习惯。
*/
public class Factory {
public static void main(String[] args) {
// 不用工厂模式之前操作
// Animal animal;
// animal = new Dog();
// animal = new Dog("二哈");
// animal = new newTiger();
// animal.eat();
// animal = new Cat();
// 使用工厂模式之后操作
FactoryAnimal factoryAnimal = new FactoryAnimal();
Animal animal = factoryAnimal.getAnimalInstance("Tiger");
animal.eat();
}
}
interface Factory2 {
Animal getDogName(String name);
Animal getDogNameId(String name, String id);
}
// 工厂加载类
class FactoryAnimal {
public Animal getAnimalInstance(String className) {
if (className.equals("Dog")) {
return new Dog();
} else if (className.equals("DogName")) {
return new Dog("二哈");
} else if (className.equals("Cat")) {
return new Cat();
} else if (className.equals("Tiger")) {
return new newTiger();
} else if (className.equals("Pig")) {
return new Pig();
} else if (className.equals("Bird")) {
return new Bird();
} else {
return null;
}
}
public Animal getDogName(String name) {
return new Dog(name);
}
public Animal getDogNameId(String name, String id) {
return new Dog(name, id);
}
}
// 父接口
interface Animal {
void eat();
}
// 狗类
class Dog implements Animal {
private String name;
private String id;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public Dog(String name, String id) {
this.name = name;
this.id = id;
}
@Override
public void eat() {
System.out.println("狗狗在吃狗粮。。。。");
}
}
// 猫类
class Cat implements Animal {
@Override
public void eat() {
System.out.println("布偶猫在吃小鱼儿。。。");
}
}
// 老虎类
class Tiger implements Animal {
@Override
public void eat() {
System.out.println("老虎在吃小绵羊。。。");
}
}
// 老虎类
class newTiger extends Tiger {
@Override
public void eat() {
System.out.println("新品种的老虎会爬树。。。。");
}
}
// 猪类
class Pig implements Animal {
@Override
public void eat() {
System.out.println("小猪猪在抢小狗的狗粮吃。。。。");
}
}
// 鸟类
class Bird implements Animal {
@Override
public void eat() {
System.out.println("小鸟在吃小毛虫。。。。");
}
}
代理模式:
package com.schema;
/**
* 代理模式:
* 在我们程序开发的过程中,有很多的操作并不是主业务代码(比如日志、权限、事务。。),就会造成代码特别膨胀(代码多、里面不止一个业务逻辑代码),
* 然后我们开发的时候需要进行这些代码修改维护极为不便,也就是可读性及维护性很低,所以我们可以使用代理模式来进行处理,代理模式顾名思义就是将
* 我们非当前主业务的代码放到其他地方去处理
*/
public class Proxy {
public static void main(String[] args) {
Arithmetic arithmetic = new ArithmeticImpl();
System.out.println(arithmetic.add(10,3));
System.out.println(arithmetic.sub(10,3));
System.out.println(arithmetic.mul(10,3));
System.out.println(arithmetic.div(10,3));
}
}
interface Arithmetic {
Integer add(int x, int y);
Integer sub(int x, int y);
Integer mul(int x, int y);
Integer div(int x, int y);
}
class ArithmeticImpl implements Arithmetic {
@Override
public Integer add(int x, int y) {
int result = x + y;
return result;
}
@Override
public Integer sub(int x, int y) {
int result = x - y;
return result;
}
@Override
public Integer mul(int x, int y) {
int result = x * y;
return result;
}
@Override
public Integer div(int x, int y) {
int result = x / y;
return result;
}
}
package com.schema;
/**
* 现在需求改了,需要将我们加减乘除方法处理的前后增加操作日志:
*/
public class Proxy {
public static void main(String[] args) {
Arithmetic arithmetic = new ArithmeticImpl();
System.out.println(arithmetic.add(10, 3));
System.out.println(arithmetic.sub(10, 3));
System.out.println(arithmetic.mul(10, 3));
System.out.println(arithmetic.div(10, 3));
}
}
interface Arithmetic {
Integer add(int x, int y);
Integer sub(int x, int y);
Integer mul(int x, int y);
Integer div(int x, int y);
}
class ArithmeticImpl implements Arithmetic {
@Override
public Integer add(int x, int y) {
System.out.println("the method add start");
int result = x + y;
System.out.println("the method add end");
return result;
}
@Override
public Integer sub(int x, int y) {
System.out.println("the method sub start");
int result = x - y;
System.out.println("the method sub end");
return result;
}
@Override
public Integer mul(int x, int y) {
System.out.println("the method mul start");
int result = x * y;
System.out.println("the method mul end");
return result;
}
@Override
public Integer div(int x, int y) {
System.out.println("the method div start");
int result = x / y;
System.out.println("the method div end");
return result;
}
}
package com.schema;
/**
* 我们可以明显看到日志的代码和业务代码在一块了,如果我现在要改日志或者业务代码就会很麻烦,要时刻注意会不会改到另一块的代码
* 现在我们使用代理模式来看看,发现了日志代码和逻辑代码完全分离开了,改日志代码基本上不会影响到主业务代码了。
*/
// 测试类
public class Proxy {
public static void main(String[] args) {
Arithmetic arithmetic = FactoryArithmetic.getFactoryArithmetic();
System.out.println(arithmetic.add(10, 3));
System.out.println(arithmetic.sub(10, 3));
System.out.println(arithmetic.mul(10, 3));
System.out.println(arithmetic.div(10, 3));
}
}
// 使用工厂模式进行实例化
class FactoryArithmetic {
public static Arithmetic getFactoryArithmetic() {
return new ArithmeticProxyImpl();
}
}
// 算数接口
interface Arithmetic {
Integer add(int x, int y);
Integer sub(int x, int y);
Integer mul(int x, int y);
Integer div(int x, int y);
}
// 使用算数代理实现类完成日志操作
class ArithmeticProxyImpl implements Arithmetic {
// 定义主业务实现类
private ArithmeticImpl arithmetic;
public ArithmeticProxyImpl() {
this.arithmetic = new ArithmeticImpl();
}
@Override
public Integer add(int x, int y) {
System.out.println("the method add end");
Integer result = arithmetic.add(x, y);
System.out.println("the method add start");
return result;
}
@Override
public Integer sub(int x, int y) {
System.out.println("the method sub start");
Integer result = arithmetic.sub(x, y);
System.out.println("the method sub end");
return result;
}
@Override
public Integer mul(int x, int y) {
System.out.println("the method mul start");
Integer result = arithmetic.mul(x, y);
System.out.println("the method mul end");
return result;
}
@Override
public Integer div(int x, int y) {
System.out.println("the method div start");
Integer result = arithmetic.div(x, y);
System.out.println("the method div end");
return result;
}
}
// 算数实现类
class ArithmeticImpl implements Arithmetic {
@Override
public Integer add(int x, int y) {
int result = x + y;
return result;
}
@Override
public Integer sub(int x, int y) {
int result = x - y;
return result;
}
@Override
public Integer mul(int x, int y) {
int result = x * y;
return result;
}
@Override
public Integer div(int x, int y) {
int result = x / y;
return result;
}
}
模板模式:
抽象类就是体现一种模板的设计,抽象类作为多个子类通用的模板,子类在抽象类的基础上进行功能的扩展、改造,但是子类总体上还是会保留抽象类的行为方式。模板设计模式解决的问题是:
- 当需求的功能一部分是确定的,一部分是不确定的,这个时候我们可以将不确定的部分暴露出去,让子类去实现。
- 编写一个抽象类,服了提供了多个子类通用的方法,并且把一个或者多个不确定的实现留给子类去实现,就是模板设计模式的实现。
我们可以看到下面的例子将所有的动物类抽象成animal类,那么我们就可以将所有动物都设计有吃饭和睡觉的行为,不管子类怎么去使用,都必须实现我们抽象类设计的行为。
package com.demo;
/**
* 抽象类:为动物类 animal 需要有子类 dog、cat、pig、tiger、bird
*/
public class OopAbstractDemo04 {
public static void main(String[] args) {
Animal2 an;
an = new Dog2("二哈", 3);
an.eat();
an.sleep();
an = new Tiger2("大宝",4);
an.eat();
an.sleep();
}
}
// 动物类 父类
abstract class Animal2 {
// 姓名
private String name;
// 年龄
private Integer age;
public Animal2() {
}
public Animal2(String name, Integer age) {
this.name = name;
this.age = age;
}
// 吃饭
public abstract void eat();
// 睡觉
public abstract void sleep();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
class Dog2 extends Animal2 {
public Dog2() {
}
public Dog2(String name, Integer age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(super.getName() + "狗在吃狗粮!!!");
}
@Override
public void sleep() {
System.out.println(super.getName() + "睡在狗窝。。");
}
}
class Tiger2 extends Animal2 {
public Tiger2() {
}
public Tiger2(String name, Integer age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(super.getName() + "老虎在吃小绵羊。。");
}
@Override
public void sleep() {
System.out.println(super.getName() + "老虎在动物园睡觉。。。");
}
}