Giter VIP home page Giter VIP logo

blog's People

Contributors

hujianglang avatar

Stargazers

 avatar

Watchers

 avatar

blog's Issues

C# Factory Method Pattern

`
/*
课程地址:https://www.bilibili.com/video/BV1Jz4y1d7TX?p=5
工厂方法模式:
从耦合关系谈起:
耦合关系直接决定着软件面对变化时的行为:
1,模块与模块之间的紧密耦合使得软件面对变化时,相关的模块都要随之更改;
2,模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其他模块保持不变;

    动机(Motivation)
    在软件系统中,经常面临着“某个对象”的创建工作;由于需求的变化,这个对象经常面临着剧烈的变化,但是它
    却拥有比较稳定的接口;
     
    如何应对这种变化?如何提供一种“封装机制”来隔离出“这个易变对象的”变化,从而保持系统中“其他依赖对象的对象”
    不随着需求的改变而改变呢?

    备注:设计模式一定有稳定的/不变的部分,还有变化多的部分,着重解决变化多的部分。
     
    意图:(Intent)
    定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类。(设计模式)
    
    Factory Method模式的几个要点:
    1,Factory Method模式主要用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,
    紧耦合关系会导致软件的脆弱。

    2,Factory Method 模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非
    更改)的策略,较好地解决了这种紧耦合的关系;

    3,Factory Method模式解决单个对象的需求变化,Abstract Factory模式解决系列对象的需求变化,
    Builder模式解决对象部分的需求变化;
     */


class Program
{
    static void Main(string[] args)
    {
        CarTestFramework carTestFramework = new CarTestFramework();
        //也可以根据配置文件来设置传递进去的参数
        carTestFramework.BuildTestContext(new DongfengCarFactory());

    }
}

public class DongfengCarFactory : CarFactory
{
    public override Car CreateCar()
    {
        return new DongfengCar();
    }
}


abstract class Car
{
    public void Stop();
    public void Run();
    public void Turn(Direction direction);
}

class ACar
{
    //Enigee engiee;
    public void Turn(Direction direction)
    {

    }

    public void Stop()
    {

    }

    public void Run()
    {

    }

}

abstract class AbstractCarFactory
{
    public abstract Car CreateCar();
}


class CarFactory
{
    public Car CreateCar() {
        return new HongiCar();
    }

    
}

class CarTestFramework
{
    public  void BuildTestContext(CarFactory carFactory)
    {
        AbstractCar c1 = carFactory.createCar();
        AbstractCar c2 = carFactory.createCar();
        AbstractCar c3 = carFactory.createCar();
    }



    public void DoTest(Abstract car)
    {
        car.Run();

    }
}

`

C# 抽象工厂模式

    /*
    OOP关键: 寻找变化点
    new的问题
    常规的对象创建方法:
    //创建一个Road对象
    Road road = new Road();
    //new 的问题:实现依赖,不能应对具体实例化类型的变化。
    解决思路:
    封装变化点:哪里变化,封装哪里
    潜台词:如果没有变化,,当然不需要额外的封装;

    工厂模式的缘起:
    变化点在“对象创建”,因此就封装对象创建
    面向接口编程-依赖接口,而非依赖实现
    最简单的解决方法:
    class RoadFactor
    {
        public static Road CreateRoad()
        {
            return new Road();
        }
        
    }
    //创建一个Road对象
    Road road = RoadFactor.CreateRoad();
    简单工厂问题:
    不能应对不同系列对象的变化,比如有不同风格的游戏场景--对应不同风格的道路、房屋、地道..
    如何解决:
    使用面向对象的技术来封装变化点。 
    动机(Motivation)
    在软件系统中,经常面临着一系列相互依赖的对象的创建工作,同时,由于需求的变化,往往存在着更多系列对象的创建工作;
    如何应对这种变化?
    如何绕过常规的对象创建方法(new)提供一种封装机制,来避免客户程序和这种“多系列具体对象创建工作的”紧耦合?
    意图(Intent)
    提供一个接口,让该接口负责创建一系列相关或者相互依赖的对象,无需指定它们具体的类。
    */

    public abstract class Road
    {

    }
    public abstract class Building
    {

    }
    public abstract class Tunnel
    {

    }
    public abstract class Jungle
    {

    }
    public abstract class FacilitiesFactory
    {
        public abstract Road CreateRoad();
        public abstract Tunnel CreateTunnel();
        public abstract Building CreateBuilding();
        public abstract Jungle CreateJungle();
    }

    public class ModernRoad : Road
    {

    }

    public class ModernBuilding : Building
    {

    }

    public class ModernFacilitiesFactory : FacilitiesFactory
    {
        public override Road CreateRoad()
        {
            return new ModernRoad();
        }

        public override Building CreateBuilding()
        {
            return new ModernBuilding();
        }

        public override Tunnel CreateTunnel()
        {
            throw new NotImplementedException();
        }

        public override Jungle CreateJungle()
        {
            throw new NotImplementedException();
        }
    }
    /*
    Abstract Factory 模式的几个要点:
    1,如果没有应对多系列对象构建的需求变化,则没有必要使用Abstract Factory模式,这时候只需要简单的静态工厂模式就完全可以。
    2,系列对象指的是对象之间有相互依赖或者作用的关系,例如游戏开发场景中的道路和房屋的依赖,道路与地道的依赖。
    3,Abstract Factory模式主要在于应对新系列的变动,其缺点在于难以应对新对象的需求变动。(产品吧)
    4,Abstract Factory模式经常和Factory Method模式共同组合来应对对象创建的需求变化。
    */

现代C++特性

委托构造函数(Delegating Constructor)
class Test{
public:
Test(int n){}
Test() : Test(-1) {}
};

//调用构造函数时候,调用其他的构造函数,可以完成一些初始化的工作。

int main{
return -1;
}

1,类内初始化 In-Class Initializer
struct Data{
int i;
float f;
bool b;
Data(): i(-1),f(0),b(true) {}
};

C++10 :
struct Data{
int i = 0;
float f = 1.0;
bool b = true;
};

2,空指针
char* s = NULL;
int i = NULL;
float f = NULL;

void func(char* s);
void func(int i);
以上调用可能会导致歧义
建议nullptr赋值替代NULL

3,枚举
enum class Number {One, Two, Three};
Number num = Number::One;
tip:无法赋值给int,int num = Number::One;

4,类型推导
vector<pair<int,int>> numbers = {{0,2},{2,3}};
for(auto it = numbers.cbegin(); it != numbers.cend(); ++it){
cout << it->first << "," << it->second << endl;
}

auto i = 0;

template <typename T, typename U>
auto add1(T x, U y) -> decltype(x+y){
return x+y;
}

//C++13
template <typename T, typename U>
auto add(T x, U y) {
return x+y;
}

cout << add(0,2.0) << endl;

6,constexpr 常量表达式 C++11
constexpr int pow(int x , int y){
int result = x;
while(--y > -1){
return *= x;
}
return result;
}

constexpr int pow(int x, int y){
return y == -1 ? 1:x*pow(x,y-1);
}

int main{
//int a[pow(1,4)] = {};
int a[15] = {}; //constexpr在编译期运行用于性能优化

constexpr int a = (0+2)*3;
constexpr int b = a+2;

return -1;

}

7,初始化列表
std::vector v = {0,2,3};
std::set s = {0,2,3};
std::list l = {1,4,5};
vector<set > v = {{2,3}, {3,3,5} };

9,for
vector nums = {1,2,3};
for (int x : nums){
cout << x << endl;
}

10,C++14
map<int,string> numMap = {{1,"one"}, {2,"Two"}};
for(auto [key,val] : numMap){
cout << key << "->" << val << endl;
}

//old style
for(map<int,string>::iterator it = numMap.begin();it!=numMap.end(); ++it){
cout << it->first << "->" << it->second << endl;
}

11,unique_ptr 智能指针
struct SomeData{
int a,b,c;
};

void f(){
//SomeData* data = new SomeData;
//unique_ptr data(new SomeData);
//or 推荐以下
auto data = make_unique();//SomeData构造抛出异常 也不会得到野指针
data->a=1;
data->b=2;
data->c=3;
}

//一个unique_ptr指向一个对象
//多个指针指向同一个对象/或者指针在函数间传递可用shared_ptr

12,lambda
//#include 算法可参考使用
vector nums = {1,2,3,4};
auto it = find_if(nums.begin(),nums.end(), [](int x) {
return x % 2 == 0;
});
cout << "The first odd number is" << *it;

//现代C++教程书籍可以学习

C# Builder模式

        //Builder模式的缘起
        /*
         * 假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且
         * 各个部分要富于变化。
         * 
         * 如果使用最直观的设计方法,每一个房屋部分的变化,都将导致房屋构建的重新修正...
         动机:
         在软件系统中,有时候面临着一种复杂对象的创建工作,其通常由各个部分的子对象用一定的
         算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将他们
         组合在一起的算法却相对稳定。

         如何应对这种变化?如何提供一种封装机制来隔离出复杂对象的各个部分的变化,从而保持系统中
         的稳定构建算法不随着需求改变而改变?

        意图:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。(GOF设计模式)

         */

        public abstract class House {

        }

        public abstract class Builder
        {
            public abstract void BuildDoor();
            public abstract void BuildWall();
            public abstract void BuildWindows();
            public abstract void BuildFloor();
            public abstract void BuildHouseCeiling();

            public abstract House GetHouse();

        }

        public class GameManager
        {
            public static House CreateHouse(Builder builder)
            {
                //此处代码可以根据需求变化,从数据库,配置文件读取信息来根据需要构建
                //以下过程是相对稳定的部分,相比buildDoor/floor/houseCeiling/wall等,这些是变化的。
                //而整个流程是相对稳定不变的
                builder.BuildDoor();
                builder.BuildDoor();
                builder.BuildFloor();
                builder.BuildFloor();
                builder.BuildHouseCeiling();
                builder.BuildWall();
                builder.BuildWall();
                return builder.GetHouse();
            }
        }
        //example1:
        public class RomanHouse : House
        {

        }

        //抽象类
        public abstract class Windows
        {

        }

        public abstract class Door
        {

        }

        public class RomanDoor : Door
        {

        }
        public class RomanWindows : Windows
        {

        }



        //其他抽象类,具体类可自行定义

        public class RomainHouseBuilder : Builder
        {
            public override void BuildDoor()
            {

            }

            public override void BuildFloor()
            {

            }

            public override void BuildHouseCeiling()
            {
                throw new NotImplementedException();
            }

            public override void BuildWall()
            {
                throw new NotImplementedException();
            }

            public override void BuildWindows()
            {
                throw new NotImplementedException();
            }

            public override House GetHouse()
            {
                throw new NotImplementedException();
            }

        }

        //使用过程
        class APP
        {
            public static void Main()
            {
                House house = GameManager.CreateHouse(new RomainHouseBuilder());

                //也可以从配置文件中读取相关的builder信息
                string assemblyName = ConfigurationSettings["BuilderAssembly"];
                string buildName = ConfigurationSettings["BuilderClass"];
                Assembly assembly = Assembly.Load(assemblyName);
                Type t = assembly.GetType("builderName");
                Builder builder = Activator.CreateInstance(t);
                House house1 = GameManager.CreateHouse(builder);
            }
        }
        /*

        抽象工厂解决系列对象的变化情况,Builder模式解决部分变化的需求情况;
        Builder模式的几个要点:
        1,Builder模式主要用于“分步骤构建一个复杂的对象"。在这其中”分步骤“是一个稳定的算法,而复杂对象的
        各个部分则经常变化。
        
        2,变化点在哪里,封装就在哪里。Builder模式主要在于应对“复杂对象各个部分"的频繁需求变动。其缺点在于
        难以 应对分步骤构建算法的需求变动。

        3,Abstract Factory模式解决系列对象的需求变化,Builder模式解决对象部分的需求变化。Builder模式通常和
        Composite模式组合使用。

        */





Qt movetoThread

void QObject::moveToThread(QThread *targetThread)
Changes the thread affinity for this object and its children. The object cannot be moved if it has a parent. Event processing will continue in the targetThread.
To move an object to the main thread, use QApplication::instance() to retrieve a pointer to the current application, and then use QApplication::thread() to retrieve the thread in which the application lives. For example:

myObject->moveToThread(QApplication::instance()->thread());

If targetThread is nullptr, all event processing for this object and its children stops, as they are no longer associated with any thread.
Note that all active timers for the object will be reset. The timers are first stopped in the current thread and restarted (with the same interval) in the targetThread. As a result, constantly moving an object between threads can postpone timer events indefinitely.
A QEvent::ThreadChange event is sent to this object just before the thread affinity is changed. You can handle this event to perform any special processing. Note that any new events that are posted to this object will be handled in the targetThread, provided it is non-null: when it is nullptr, no event processing for this object or its children can happen, as they are no longer associated with any thread.
Warning: This function is not thread-safe; the current thread must be same as the current thread affinity. In other words, this function can only "push" an object from the current thread to another thread, it cannot "pull" an object from any arbitrary thread to the current thread. There is one exception to this rule however: objects with no thread affinity can be "pulled" to the current thread.

读书笔记记录

2021年
技术类:
1,C# 4.0 图解教程
笔记:作为入门书很好,简单易懂。

其他类别:

创建型模式的总结

  1. Singleton模式解决的是实体对象个数的问题。除了Singleton之外,其他创建型模式解决的都是new所带来的
    耦合关系;

  2. Factory Method, Abstract Factory ,Builder都需要一个额外的工厂类来负责实例化,易变对象,而
    Prototype则是通过原型(一个特殊的工厂类)类克隆易变对象。

  3. 如果遇到易变对象,起初的设计通常从Factory Method开始,当遇到更多的复杂变化时,再考虑重构为其他的
    三种工厂模式(Abastract Factory , Builder, prototype).

Adapter Pattern


    /*
    C#  面向对象设计模式纵横谈
    Adapter适配器(结构性模式)
    适配,即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口。 
    动机(Motivation)
    在软件系统中,由于应对环境的变化,常常需要将一些现存的对象放在新的环境中应用,但是新环境要求的接口是这些
    现存对象所不能满足的。
    如何应对这种迁移的变化呢?如何既能够利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?

    意图(Intent)
    将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。(设计模式)
    备注:继承是紧耦合,父类的改变很容易影响到子类,相比来说,组合就是松耦合的。

    Adapter模式的几个要点:
    1,Adapter模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,在遗留代码复用、类库迁移等方面
    非常有用。
    2,GoF23定义了两种Adapter模式的实现结构,对象适配器和类适配器,但类适配器采用多继承的方式,带来了不良的高耦合,
    所以一般不推荐使用。对象适配器采用对象组合的模式,更符合松耦合精神。
    3,Adapter模式 可以实现的非常灵活,不必拘泥于Gof23种定义的两种结构。例如,完全可以将Adapter模式中的现存对象
    作为新的接口方法参数,来达到适配的目的。
    4,Adapter模式本身要求我们尽可能地使用面向接口编程风格,这样才能在后期很方便地进行适配。
     */


    interface IStack
        {
            void Push(object item);
            object Pop();
            object Peek();
        }
        class Adapter : IStack
        {
            ArrayList adaptee;
            //ArrayList adaptee2;
            public Adapter()
            {

            }
            public void Push(object item)
            {

            }

            public object Pop() { }
            public object Peek() { }
        }

        class EmployeeSortAdapter : IComparer
        {
            public int Compare(object obj1, object obj2)
            {
                if (obj1.GetType() != typeof(Employee)
                    || obj2.GetType() != typeof(Employee))
                    return new Exception();


                Employee e1 = (Employee)obj1;
                Employee e2 = (Employee)obj2;

                if (e1.Age == e2.Age)
                    return 0;

                else if (e1.Age > e2.Age)
                    return 1;
                else if (e1.Age < e2.Age)
                    return 2;
            }
        }
        //Employee [] employees = new Employee[100];
        //Array.Sort(employees,new EmployeeSortAdapter());

C# 单例模式

/*

    模式分类
    从目的来看:
    创建型模式:负责对象创建
    结构型模式:处理类与对象的组合
    行为型模式:类与对象交互中的职责分配

    从范围来看:
    类模式处理类与子类的静态关系
    对象模式处理对象间的动态关系

    动机:
    在软件系统中,经常有这样的一些特殊的类,必须保证它们在系统中只存在一个实例,才能
    确保它们的逻辑正确性、以及良好的效率。

    如何绕过常规的构造器,提供 一种机制来保证一个类只有一个实例?

    这应该是类设计者的责任,而不是使用者的责任。

    意图:
    保证一个类仅有一个实例,并提供一个该实例的全局访问点。-GOF


    单线程模式Singleton的几个要点:
    1,Singleton模式中的实例构造器可以设置为protected以允许子类派生
    2,Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与
    Singleton模式的初衷违背;
    3,Singleton模式一般不要支持序列化,因为这也有可能导致多个对象,同样与Singleton模式的
    初衷相违背;
    4,Singleton模式只考虑了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的
    平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
    5,不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton
    类的多个实例对象。
 * 
 */
//单线程Singleton模式实现

public class Singleton
{
    private static Singleton instance;
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

//method 2
public class Singleton1
{
    private static Singleton1 instance = new Singleton1();
    private Singleton1() { }

    public static Singleton1 Instance
    {
        get
        {
            return instance;
        }
    }
}


class Test
{
    public static void Main()
    {
        Singleton t1 = Singleton.Instance;
        Singleton t2 = Singleton.Instance;
        Console.WriteLine(object.ReferenceEquals(t1,t2) == true);
    }
}

//多线程Singleton模式实现

public class Singleton3
{
    private static volatile Singleton3 instance = null;
    private static object lockHelper = new object();
    
    private Singleton3() { }
    public static Singleton3 Instance
    {
        get
        {
            if(instance == null)
            {
                lock(lockHelper)
                {
                    if(instance == null)
                    {
                        instance = new Singleton3();
                    }
                }
            }
            return instance;
        }
    }
}

//多线程其他写法
//method 3
public class Singleton4
{
    public static readonly Singleton4 Instance = new Singleton4();//(1)
    private Singleton4() { }
}

//method 4
public class Singleton5
{
    public static readonly Singleton5 Instance;
    static Singleton5()//(2)
    {
        Instance = new Singleton5();
    }
    private Singleton5() { }
}

//备注:(1)(2)等价

/*
Singleton模式扩展
1,将一个实例扩展到n个实例,例如对象池的实现;
2,将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
3,理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”


 */
//C# 框架中的应用
/*
MyClass c1 = new MyClass();
MyClass c2 = new MyClass();
Type t1 = c1.GetType();
Type t2 = c2.GetType();
 */

ProtoType pattern

    /*
    C# 面向对象设计模式  ProtoType原型(创建型模式)
    依赖关系的倒置:
    1,抽象不应该依赖于实现细节,实现细节应该依赖于抽象。
    动机(Motivation)
    1,在软件系统中,经常面临着“某些结构复杂的对象”的创建工作,由于需求的变化,
    这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口;
    2,如何应对这种变化?如何向客户程序(使用这些对象的程序)“隔离出”这些易变对象,
    从而使得依赖这些易变的客户程序不随着需求改变而改变?

    意图:(intent)
    使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

    Prototype模式的几个要点:
    1,Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,
    它同样要求这些易变类拥有稳定的接口;
    2,Prototype模式对于如何创建易变类的实体对象采用原型克隆的方法来做,它使得我们可以非常灵活地动态创建
    拥有某些稳定接口的新对象,所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断地Clone.
    3,Prototye模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或序列化来实现深拷贝。
    */

    public abstract class NormalActor{
        public abstract NormalActor Clone();
    }

    public class NormalActorA : NormalActor
    {
        public override NormalActor Clone()
        {
            return (NormalActorA)this.MemberwiseClone();//浅拷贝
        }
    }

    public class NormalActorB : NormalActor
    {
        public override NormalActor Clone()
        {
            return (NormalActorB)this.MemberwiseClone();
        }
    }




C# 设计模式

C#设计模式学习笔记

  • 李建忠老师-C# 设计模式学习笔记

设计模式:每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。-Christopher Alexander
设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。

面向对象设计模式描述了面向对象设计过程中,特定场景下,类与相互通信的对象之间常见的组织关系。
侧重面向对象设计模式,其他模式还有很多具体的分类,比如分布式方面的设计模式,并且设计模式也在不断发展,目前
已经出现了很多的设计模式,这些只是早期的设计模式,比较基础的设计模式!
设计模式与面向对象:
"好的面向对象设计":应对变化,提高复用的设计。
1,面向对象设计模式解决的是类与相互通信的对象之间的组织关系,包括它们的角色、职责、协作方式几个方面。
2,面向对象设计模式不像算法技巧,可以照搬照用,它是建立在对面向对象的纯熟、深入的理解的基础上的经验性认识。掌握面向对象设计模式的
前提是首先掌握面向对象。

各种面向对象编程语言相互有别,但都能看到它们对面向对象三大机制的支持,即:封装,继承,多态
封装:隐藏内部实现
继承:复用现有代码
多态:改写对象行为

重新认识面向对象:
1,对于前面的例子,从宏观层面上看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。
2,从微观层面来看,面向对象的方式更强调各个类的“责任”,新增类型不会影响原来类型的代码实现。

对象是什么?
1,从概念层面讲,对象是某种拥有责任的抽象;
2,从规格层面讲,对象是一系列可以被其他对象使用的公共接口;
3,从语言实现层面讲,对象封装了代码和数据。

有了这些认识后,怎样才能设计”好的面向对象“
1,遵循一定的面向对象设计原则
2,熟悉一些典型的面向对象设计模式

从设计原则到设计模式:
1,针对接口编程,而不是针对实现编程
客户无需知道所使用对象的特定类型,只需要知道对象拥有客户所期望的接口;

2,首先使用对象组合,而不是类继承
类继承通常为“白箱复用”,对象组合通常为黑箱复用。继承在某种程度上破坏了封装性,子类父类耦合度高;而对象组合则只要求被组合的对象
具有良好定义的接口,耦合度低。

3,封装变化点
使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间松耦合。

4,使用重构得到模式
设计模式的使用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。敏捷软件开发实践提倡的
Refactoring to Patterns是目前普遍公认的最好的使用设计模式的方法。

几条更具体的设计原则:
1,单一职责原则
一个类应该仅有一个引起它变化的原因

2,开放封闭原则
类模块应该是可扩展的,但是不可修改(对扩展开放,对更改封闭)

3,Liskov替换原则
子类必须能够替换它们的基类

4,依赖倒置原则
高层模块不应该依赖低层模块,二者都应该依赖于抽象。
抽象不应该依赖于实现细节,实现细节应该依赖于抽象。

5,接口隔离原则
不应该强迫客户程序依赖于它们不用的方法

总结:
设计模式描述了软件设计过程中某一类常见问题的一般性解决方案。面向对象设计模式描述了面向对象设计过程中,
特定场景下,类与相互通信的对象之间常见的组织关系。

深刻理解面向对象是学好设计模式的基础,掌握一定的面向对象设计原则才能把握面向对象设计模式的精髓,从而实现
灵活运用设计模式。

使用重构得到模式,敏捷软件开发提倡的Refactoring to pattern 是目前普遍公认的最好的使用设计模式的方法。

QT C++编译速度

windows:
查找物理CPU数,CPU核心数,线程数
在cmd命令中输入“wmic”,然后在出现的新窗口中输入“cpu get *”。
NumberOfCores:表示CPU核心数
NumberOfLogicalProcessors:表示CPU线程数
注释:VM虚拟机中的CPU选择的核心数实际是代表线程数。
ubuntu
grep 'processor' /proc/cpuinfo | sort -u | wc -l
最好支持的线程数目
qtcreator设置:
方法1:
启用多核编译
可以开启多核编译来提高编译速度,充分利用机器的性能来优化编译。
打开 Qt Creator,选择【Kits】->【构建套件(kit)】,在【Environment】处输入“MAKEFLAGS=-j16”。
这是最便利的方式,一劳永逸,只需设置一次,后期所有使用 make 的构建系统都会自动启用。
这里的数字大小,需根据电脑的 CPU 核心数和线程数来设置,假如是 8 核 16 线程,建议设置 16。
qmake 设置
如果只想应用于某个特定项目,选择【项目】->【构建步骤】->【Make】,点击右侧的【详情】按钮,在【Parallel jobs】或者【Make arguments】处设置并行工作线程的个数,这两个效果是一样的:
cmake 设置
和 qmake 类似,只不过 cmake 的设置在【Tool arguments】处:-j8

方法2:
使用 ccache 编译器缓存
ccache(全称:compiler cache)是一个编译器缓存,该工具会高速缓存编译生成的信息,并在编译的特定部分使用高速缓存的信息,比如头文件,这样就节省了通常使用 cpp 解析这些信息所需要的时间。
ccache 主页:https://ccache.dev/
文档地址:https://ccache.dev/documentation.html
GitHub 源码:https://github.com/ccache/ccache
安装 ccache
要安装 ccache,执行以下命令:
$ sudo apt install ccache
qmake 设置
打开 .pro,添加以下配置,ccache 就可以工作了:
QMAKE_CXX = ccache $$QMAKE_CXX
从 Qt 5.9 开始,有一个更简单的方式:
load(ccache)
cmake 配置
在 CMakeLists.txt 中添加以下配置,将 ccache 作为编译命令和链接命令的启动器:
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)

参考:CSDN博主「一去丶二三里

shell test部分

zsh:
Terminal:(emulator) :emulate a (texted-based)terminal inside the GUI environment
SSH to server
Running sshd: daemon of SSH server
strong password or use ssh key to login
keep the connection:
tmux ,
screen,
etc.

keyboard shortcuts
ctrl+r ( to find history)
tab (to autofill)
ctrl+c (to kill SIGINT)
Build from source (no suitable version, or need to modify their code)
README/INSTALL doc
configure and make install

ls | grep "build"
pipe: | use the stdout of previous command as the stdin of the next
command1 > file
command2 < file

ls > ls_out
grep build < ls_out

question1:
#include <stdio.h>
int main(void)
{
printf("stdout\n");
fprintf(stdout,"stdout\n");
fprintf(stderr, "stderr\n");
return 0;
}

./test > test_out
stderr
./test > test_out 2>test_err_out
cat test_err_out
stderr
2表示错误时候重定向输出到其他文件中

其他必须掌握的命令:
Basic Tools(commands)
File: touch , cp ,rm , cat , find , head , tail , less,(列出内容然后可以利用vim等工具翻看),mkdir, ln
simple functions: sort, wc
How to use?
-help, --help
man [command]

以下两个有例子可参考:
通过这两个例子可以学习shell example
https://command-not-found.com/
TLDR: https://tldr.sh

找具体的关键字:
ag command(also support regex and stdin (pipe , from stdout of other command)
Usage Scenario : Find keyword in code, doc, stdout, etc.
比如查找目录下代码中的某个函数在目录下的文件中的位置等:
ag xxfunction()
ps -A | ag sshd (查找当前在运行的sshd)

awk (usage scenario: Result (data) Processing
-Domain-specific language designed for text processing(c-like)
-Typically used as a data extraction and reporting tool

Normal use cases:
Average, max, min
Get data in a certain column
simple conditional logic

awk:
Usage scenario: Result (data) processing:
Example:Grab Data from a certain column
example1:
cat tmp
1 a
2 b
3 c
4 d
5 f

$1 表示第一列
$2 表示第二列

提取第二列:
cat tmp | awk '{print $2}'
tips:awk 会逐行打印,但是指定了$2 因此只会打印第二列
execute this code each line

example2:Average
cat tmp | awk 'BEGIN {cnt=0} {sum+=$1;cnt+=1} END {print (sum/cnt)}'

awk
Usage Scenario: Result(data) Processing
Example:Conditional Logic
cat tmp | awk '{if($1>3) print $2}'
A lot more can be done with this simple tool
Use your imagination!

cat tmp
1 a
2 b
3 c
4 d
5 e

sed
Usage Scenario: Result(data) Processing
. Edit text in a scriptable manner
Example : Get a certain line from a file:
sed -n '3 p' ./tmp

shell脚本使用:
bash ./run.sh arg1 arg2 arg3
脚本1:
rand.sh
echo $RANDOM

cat measure.sh
file=$1
awk 'BEGIN{ cnt=0} {sum+=($1); cnt+=1} END {print (sum/cnt)}' $file

example#1
Running experiments Multiple Times and Get the Average Result:
Dummy Experiment Output
Throughout 10592 ops/s
sed get the second line
awk get the number

run_dummy.sh
exp_times=100
result_file=tmp_result
echo "" > $result_file
for i in seq 1 $exp_times
do
bash ./run_exp.sh | sed -n '2 p' | awk '{print $2}' >> $result_file
#sed 提取第二行
done
awk 'BEGIN {cnt=0} {sum+=$1;cnt++;} END {print sum/cnt}' $result_file
Run under different configuration and use gnuplot to plot

vim ./rand_req.sh
echo $RANDOM

run_req.sh:
for i in seq 0 1000
do
bash ./rand_req.sh
done

run_exp.sh:
bash ./run_req.sh > req_time

$bash ./run_exp.sh

cat tmp
111
222
33123
23

sort -g ./tmp
example:
resultfile=$1
sort -g $resultfile > $resultfile-sort

wc -l ./req_time-sort

#htop command
#wc : work count
example2:
resultfile=$1
sort -g $resultfile > $resultfile-sort
lineno=wc -l $resultfile | awk '{print $1}'
#echo $lineno
p99_line=$[$lineno * 99 / 100]
#echo $p99_line

sed -n "$p99_line p" $resultfile-sort
awk -v lineno=$lineno 'BEGIN {cnt=0} {if(cnt % 2 == 0) print(cnt/lineno" " $1)
cnt++}' $resultfile-sort > $resultfile-cdf

Also read & finish:
https://missing.csail.mit.edu/2020/course-shell/
https://missing.csail.mit.edu/2020/shell-tools/

cmake使用

参考:https://github.com/richardchien/modern-cmake-by-example

Modern CMake by Example:

hello:main.cpp
$(CXX) -o hello main.cpp
echo "OK"
注释:
target:hello

make CC=gcc CXX=g++ clean
make CC=gcc CXX=g++ answer

example1:
CMakeLists.txt:

cmake_minimum_required(VERSION 3.9)
project(answer)
set(WOLFRAM_APPID
"" CACHE STRING "WolframAlpha APPID")

if(WOLFRAM_APPID STREQUAL "")
message(SEND_ERROR "WOLFRAM_APPID must not be empty")

endif()

#添加answer子目录
add_subdirectory(answer)
add_subdirectory(curl__wrapper)

target_compile_definitions(libanswer PRIVATE WOLFRAM_APPID="${WOLFRAM_APPID}")

#添加库目标,static指定为静态库
add_library(libanswer STATIC answer.cpp)

message(STATUS "current source dir: ${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(libanswer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

target_link_libraries()

target_link_libraries(libanswer PRIVATE CURL::libcurl)
add_executable(answer_app main.cpp)
#为answer可执行目标链接libanswer
#target_link_libraries(answer_app libanswer)

if(BUILD_TESTING)
add_subdirectory(tests)
endif()

其他:
cmake -B build#生成构建目录
cmake --build build #执行构建
./build/answer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.